Xcode 10 framework test: unable to find any xcassets?

I have a large-ish Xcode project that builds a framework, extension and application. The framework has logic tests, and embeds xcasset resources used by both the extension and the application. Some of the logic tests validate that all of the required xcassets can be found, so that when the application calls the framework to obtain them, they're in a known good state, and should never fail to load them. In particular, the framework wraps calls to UIImage(named: in:) with the bundle parameter set to the framework.


Under Xcode 9.4, the logic tests run, verify that all of the required xcassets are present, and succeed. Under Xcode 10 beta 1, none of the xcassets can be found. I've used Clean Build Folder several times under both Xcode 9.4 and 10. Xcode 9.4 always succeeds, Xcode 10 spectacularly fails. If I build the application, it is able to launch, and run when built with Xcode 9.4, but with Xcode 10, the application also fails to find any framework xcassets, in the same way as the logic tests fail under Xcode 10. No code changes have been applied to any source code or the project settings yet (the exact same project assets and source code are being used in both cases).


In the verbose build output, the only differences between the builds are:


  • Xcode 10 is using full paths to xcasssets when invoking CompileAssetCatalog
  • Xcode 9.4 is exporting PATH before invoking actool
  • The respective actool is being invoked (Xcode or Xcode-beta in the path)
  • --filter-for-device-os-version is 12 for Xcode 10, and 11.4 for Xcode 9.4


The resulting Assets.car file is 26.4 MB in size for Xcode 10, and 32.2 MB for Xcode 9.4.


Does anyone have any ideas what might be going on, what I might check for, next? I'm not sure if this is an asset catalog compilation bug, but I would rule out an XCTest related build bug, since the application has the same problem as the logic tests.

Replies

Bumping this. Beta 2 continues to exhibit the same problem: successful build, and missing assets. The same project targets and unit tests run and pass under Xcode 9.4.1, but fail under Xcode 10 beta or beta 2.

Given that this is a regression from 9.4, it seems reasonable for you to file a bug report about this. Please post your bug number, just for the record.

It would be helpful if you tried extracting the code from your app into a small test project and included that in the bug report. Come to think of it, that’d be useful regardless. You might find that the test project always works, in which case you can start looking at the differences between it and your main project.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Fair enough. I'm working on isolating the relevant code in the real framework project, while also trying to build up a standalone test case from an empty framework project, but this takes a great deal of time to do right... "Bisect, bisect, bisect..." Currently, the standlone test case passes (with copies of all of the assets), but the real framework target project is still failing (with 95% of unrelated code removed). I haven't pruned enough from the real code yet, to identify what's different from the test case.


One thing I noticed while adding print statements in both:


* When I call Bundle(for: MyClass.self) in a hacked-and-slashed version of MyClass in the standalone test case, the path of it is under Derived. I checked, and MyClass.swift is only included in the framework target, not the unit test target. This is expected.

* When I call Bundle(for: MyClass.self) in the real code (with or without 95% of unrelated code removed), the path of it is under Xcode beta.app, specifically: /Applications/Xcode-beta.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Agents. This is very unexpected, and is why the assets aren't being found. I don't know why this is happening. I checked, and MyClass.swift is only included in the framework target, not the unit test target. Under Xcode 9.4.1, the path is under Derived, as expeced.


I am passing Bundle(for: MyClass.self) as the bundle to load the UIImage from, in both the standalone framework test case and the real framework project, because it's a framework asset. In both cases, the bundle is being created inside a call in the framework.


If I use the Bundle(identifier:) with the bundle identifier instead of Bundle(for:) with the class.self, I can force it to work in the real code.


Puzzle: why isn't Bundle(for: MyClass.self) working in the real code, and why is it working in the standalone test case?

OK, I filed Apple Problem 41497418, "Presence of a URL property in a Swift class causes Bundle(for: <class>.self) to return wrong path"


This is kind of wild, to me. It had nothing to do with the xcassets, it instead had to do with how I am specifying the bundle containing the assets. I was using Bundle(for: MyClass.self), and if MyClass contained a let or var URL property, the path for the bundle was inside Xcode beta.app, which is wildly incorrect, instead of inside the framework bundle (in Derived), which would be correct.


After filing the bug report, I further simplified the steps:


1. Create an Xcode project, select iOS, Cocoa Touch Framework, Swift, Include Unit Tests, name it BundleMadness.

2. Create a Swift source file, name it Madness.swift, with the following:


import UIKit

public class Madness {
    
    // Comment out this line, and notice the test passes.
    internal var randomlyNamedURL: URL? // <== THIS causes Bundle(for: Madness.self) to return the wrong path

    internal var somePathToFrameworkBundle: String = ""
    
    public init() {
        let bundle = Bundle(for: Madness.self)
        self.somePathToFrameworkBundle = bundle.bundlePath
    }
    
}


3. Replace the guts of the XCTest in BundleMadnessTests.swift with the following:


    func testTheMadness() {
        let madness = Madness()
        print("path = \(madness.somePathToFrameworkBundle)")
        XCTAssertFalse(madness.somePathToFrameworkBundle.contains("Xcode-beta"), "Yo, what?")
    }


4. Build and run the unit test. Notice it fails. Comment out the line containing the URL property declaration. Build and run again. Notice it passes.

This is kind of wild, to me.

Yeah, that is weird. Thanks for filing a bug about it.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

I am having this same bug in XCode 10 GMC and have been pulling my hair out trying to figure out the issue. I did log a bug but failed to get a small reproducible case. I'll try your workaround.


I should say my real code is working but my test case fails. The bundle path looks correct in the test case and looking at the test case folder the Assets.car file is there and (in my case) so it the image but the image is not found. I also have some colors and those *are* found.


I have no URL property defined.


Edit: So I added a print statement to log the bundle path. It started working. I removed the print statement and it is still working. Very strange.

>I removed the print statement and it is still working.


Throw an option-clean build folder on top of that change and see what happens then.