Xcode Previews + SwiftPM resources - XCPreviewAgent crashed

Hello all,

There's a really frustrating crash with Xcode Previews because it cannot find the design resources package using the Bundle.module accessor (filed FB9479423). Is there something wrong with the package setup?

I have some Swift packages dependent on another package containing design resources. Xcode Previews do not work because XCPreviewAgent crashes:

CompanyDesign/resource_bundle_accessor.swift:27: Fatal error: unable to find bundle named CompanyDesign_CompanyDesign

Is there some other way packages should be locating their resources, rather than relying on the Bundle.module static property?

Others have been having this issue too. Here's a sample GitHub repo I found.

Our current work around is to build and run a new Xcode app project that includes the package as a dependency, builds the library target and uses the library API in the Simulator (Xcode Previews are a bit hit and miss in this case). But it's a really messy solution requiring us to keep unrelated Xcode projects up to date and working properly.

Any ideas?

Crash log
Process:               XCPreviewAgent [60209]
Path:                  /Users/USER/Library/Developer/Xcode/UserData/Previews/Simulator Devices/4187DDA6-B83B-4A6D-9A63-8BA6E5C73BA2/data/Containers/Bundle/Application/9CE529F9-E954-4303-9BD2-3A04C779C291/XCPreviewAgent.app/XCPreviewAgent
Identifier:            XCPreviewAgent
Version:               13.0 (19073)
Code Type:             X86-64 (Native)
Parent Process:        launchd_sim [59987]
Responsible:           SimulatorTrampoline [59322]
User ID:               501

Date/Time:             2021-08-10 10:39:26.062 +1000
OS Version:            macOS 11.5.1 (20G80)
Report Version:        12
Bridge OS Version:     5.5 (18P4759a)
Anonymous UUID:        EA6339C9-99B4-FD37-88E1-77676FE83B62

Sleep/Wake UUID:       112E14C2-9BD3-4D1C-BD53-8D0843C3E188

Time Awake Since Boot: 130000 seconds
Time Since Wake:       90000 seconds

System Integrity Protection: enabled

Crashed Thread:        0  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_BAD_INSTRUCTION (SIGILL)
Exception Codes:       0x0000000000000001, 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Termination Signal:    Illegal instruction: 4
Termination Reason:    Namespace SIGNAL, Code 0x4
Terminating Process:   exc handler [60209]

Application Specific Information:
dyld4 config: DYLD_ROOT_PATH=/Users/kgillard/Downloads/Xcode-beta.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot DYLD_LIBRARY_PATH=/Users/kgillard/Library/Developer/Xcode/DerivedData/CompanyPeopleList-euiaatprplkzjxhdopirqrpyuzvg/Build/Intermediates.noindex/Previews/CompanyPeopleList/Products/Debug-iphonesimulator DYLD_INSERT_LIBRARIES=/Users/kgillard/Downloads/Xcode-beta.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot//System/Library/PrivateFrameworks/XCPreviewKit.framework/XCPreviewKit DYLD_FRAMEWORK_PATH=/Users/kgillard/Library/Developer/Xcode/DerivedData/CompanyPeopleList-euiaatprplkzjxhdopirqrpyuzvg/Build/Intermediates.noindex/Previews/CompanyPeopleList/Products/Debug-iphonesimulator 
CompanyDesign/resource_bundle_accessor.swift:27: Fatal error: unable to find bundle named CompanyDesign_CompanyDesign
 
CoreSimulator 775 - Device: iPhone 12 (4187DDA6-B83B-4A6D-9A63-8BA6E5C73BA2) - Runtime: iOS 15.0 (19A5307d) - DeviceType: iPhone 12

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libswiftCore.dylib            	0x0000000106b482db _assertionFailure(_:_:file:line:flags:) + 427
1   CompanyPeopleList              	0x000000012f673766 closure #1 in variable initialization expression of static NSBundle.module + 2102
2   CompanyPeopleList              	0x000000012f672f19 one-time initialization function for module + 9
3   libdispatch.dylib             	0x000000010bf32c89 _dispatch_client_callout + 8
4   libdispatch.dylib             	0x000000010bf33ed8 _dispatch_once_callout + 20
5   CompanyPeopleList              	0x000000012f673941 NSBundle.module.unsafeMutableAddressor + 49
6   CompanyPeopleList              	0x000000012f6abc2b CompanyImage.safeSwiftUIImage.getter + 955
7   CompanyPeopleList              	0x000000012f6ab6be CompanyImage.swiftUIImage.getter + 142
8   PeopleListView.2.preview-thunk.dylib	0x0000000129529f2d closure #2 in closure #2 in closure #1 in CompanyPeopleListView.__preview__body.getter + 189
9   com.apple.SwiftUI             	0x0000000108760d0e Button.init(action:label:) + 70
10  PeopleListView.2.preview-thunk.dylib	0x0000000129529b9d closure #2 in closure #1 in CompanyPeopleListView.__preview__body.getter + 525
11  PeopleListView.2.preview-thunk.dylib	0x000000012952a8e1 partial apply for closure #2 in closure #1 in CompanyPeopleListView.__preview__body.getter + 17
12  com.apple.SwiftUI             	0x0000000108634c1f HStack.init(alignment:spacing:content:) + 159
13  PeopleListView.2.preview-thunk.dylib	0x0000000129528181 closure #1 in CompanyPeopleListView.__preview__body.getter + 1201
14  PeopleListView.2.preview-thunk.dylib	0x0000000129528631 partial apply for closure #1 in CompanyPeopleListView.__preview__body.getter + 17
15  com.apple.SwiftUI             	0x0000000107f16cfb NavigationView.init(content:) + 48
16  PeopleListView.2.preview-thunk.dylib	0x0000000129527b6e CompanyPeopleListView.__preview__body.getter + 606
17  CompanyPeopleList              	0x000000012f651efe CompanyPeopleListView.body.getter + 142
18  CompanyPeopleList              	0x000000012f654dc1 protocol witness for View.body.getter in conformance CompanyPeopleListView + 17
19  com.apple.SwiftUI             	0x0000000107eda535 partial apply for closure #1 in ViewBodyAccessor.updateBody(of:changed:) + 22
...
...
...```
5 Likes

This is a known issue when using resources of transitive dependencies while previewing a standalone package. Using an app as the preview host as you are doing is the recommended workaround at the moment.

1 Like

Thanks for the reply, in appreciate it because you took the time to confirm I’m on the right track.

Is there anything that can be done about it SwiftPM side that I could contribute towards or do I point people to FB9479423 and endure it in the hope it is fixed one day?

To re-iterate, while I can use Xcode projects, it’s not a great work around because I end up creating lots of unrelated projects that do not keep up with each other (if the APIs in the common package changes, I don’t get compiler errors for unopened projects). I could create less projects but that starts to affect the Xcode Previews ability to respond quickly to source changes.

5 Likes

Yep, I agree that having to create a project is not a good workaround in any way, just wanted to confirm that this is the only way to go right now.

Thanks for offering to contribute, there isn't really anything to be done from the SwiftPM side of things, this all happens inside Xcode. Basically what's happening is that normally resources only get embedded into "top level" targets such as apps, so in theory resources wouldn't work at all for previews of standalone packages. We implemented a minimal solution to support resources in the package you are actively previewing and what's missing is tackling this for transitive dependencies as well.

2 Likes

I’ve had some luck with this workaround.

That seems to fix the issue as long as the file you are previewing is directly included as a dependency in the app target. If it’s not, you need to set your active scheme to the scheme that owns that file. It’s a lot better than having to add additional app targets though!

1 Like

Thanks for sharing this! My team is trying this to mitigate Xcode project explosion until the Xcode build system can deal with all resources of the dependency graph.

I have the same problem while developing a multi-module iOS app. The question I have is if multiple module create their own Bundle extension with the same variable how Swift resolves the ambiguity? In Objective-C there is no guaranty if two modules add the same method/var in a type using a category which will be called, in Swift is there anywhere documented how this is handled?

Hi, is there any hope on this one?

1 Like

This workaround worked for me:

Really looking forward to a solution on this, since modularisation is becoming more common every day.

5 Likes

Using the SPM Plugin mechanism I've implemented this workaround by automatically generating the Bundle extension (called Bundle.current) during the prebuild phase.
It does work quite well for our project with multiple modules providing resources that are shared across targets .
An example implementation can be found here GitHub - ctreffs/swiftui-previews-module-resources-fix: Swiftui Xcode previews module resources fix

Would appreciate some feedback from the community before converting this into a standalone plugin package.

Hope this helps some of you with this problem :slightly_smiling_face:

Thanks @ctreffs for the plugin,

Do you think you can propose a PR to GitHub - apple/swift-package-manager: The Package Manager for the Swift Programming Language if the new Xcode does not fix this ?

Thanks,

I could do that, but as @NeoNacho already stated that is not a SPM thing to fix at least as far as I understand this. Opening a PR to SPM for this would leak Xcode specific implementation details to SPM which is not intended.

1 Like