Swift Playgrounds version of 'Copy Bundle Resources' build phase

Hi!

I'm participating in the Swift Student Developer competition this year, which requires developers to present a Swift Playground to Apple. I'm used to making normal Xcode projects, and am having trouble finding a Swift Playgrounds version of the Copy Bundle Resources build phase (I don't think it is possible to edit build phases in a Swift Playground).

I created a '.usdz' file from a 3D model I designed using Reality Converter and added it to the root of my Swift Playground project. I access the file programmatically from the App Bundle like so (fileName is a non-nullable String):

 guard let path = Bundle.main.path(forResource: fileName, ofType: "usdz") else { fatalError("Couldn't find the USDZ file.") }

At runtime, this throws the Couldn't find the USDZ file error, as the file isn't being copied to the App Bundle.

In a normal Xcode project, according to this StackOverflow question, I can get xcodebuild to copy my file over by specifying it in the Copy Bundle Resources build phase, however, in a Swift Playground (required by Apple), I am restricted from modifying Xcode's buildphases (the option is not present when clicking on the default target - the only options are General, Signing & Capabilites and Package Dependencies).

How can I ensure that resources are copied over to the App Bundle at buildtime in a Swift Playground?

If this is not possible, are there any other options besides using the Bundle.main.path API for accessing the USDZ file (to load a QuickLook preview) at runtime?

Accepted Reply

Hi! I am not entirely sure if Swift Packages (a Swift Playground is essentially a special type of Swift Package) support editing build phases like in Xcode projects.

When adding the folder to your playground (either by drag & drop or the plus button in the bottom left), wasn't it automatically placed within a "Resources" folder? It believe the USDZ needs to be placed within the generated Resources folder, not at the root of your playground.

Then, you can access it using Bundle.main.url (and perhaps also Bundle.main.path):

// make sure that "filename" doesn't contain the extension!
guard let url = Bundle.main.url(forResource: filename, withExtension:"usdz") else { fatalError("Couldn't find the USDZ file.") }

If you really need multiple Resources folders, a "hacky" thing you could do is to edit the Package.swift file. Control-click the Playground file in Finder and choose theShow package contents option, then open the Package.swift file and edit the target's resources:

    targets: [
        .executableTarget(
            name: "AppModule",
            path: ".",
            resources: [
                .process("Resources"),
                .process("Second Folder") // your second folder 
            ]
        )
    ]

But make sure to pay attention to the warning that you may have at the beginning of this file:

// WARNING:
// This file is automatically generated.
// Do not edit it by hand because the contents will be replaced.

This file's contents may change when you edit other settings such as the App Icon from within Xcode. From my testings the resources folders seem to stay intact, but it's good to keep the warning in mind. Thus, the best way would be to simply use the provided "Resources" folder.

Replies

Hi! I am not entirely sure if Swift Packages (a Swift Playground is essentially a special type of Swift Package) support editing build phases like in Xcode projects.

When adding the folder to your playground (either by drag & drop or the plus button in the bottom left), wasn't it automatically placed within a "Resources" folder? It believe the USDZ needs to be placed within the generated Resources folder, not at the root of your playground.

Then, you can access it using Bundle.main.url (and perhaps also Bundle.main.path):

// make sure that "filename" doesn't contain the extension!
guard let url = Bundle.main.url(forResource: filename, withExtension:"usdz") else { fatalError("Couldn't find the USDZ file.") }

If you really need multiple Resources folders, a "hacky" thing you could do is to edit the Package.swift file. Control-click the Playground file in Finder and choose theShow package contents option, then open the Package.swift file and edit the target's resources:

    targets: [
        .executableTarget(
            name: "AppModule",
            path: ".",
            resources: [
                .process("Resources"),
                .process("Second Folder") // your second folder 
            ]
        )
    ]

But make sure to pay attention to the warning that you may have at the beginning of this file:

// WARNING:
// This file is automatically generated.
// Do not edit it by hand because the contents will be replaced.

This file's contents may change when you edit other settings such as the App Icon from within Xcode. From my testings the resources folders seem to stay intact, but it's good to keep the warning in mind. Thus, the best way would be to simply use the provided "Resources" folder.

Thank you so much for your help @CMDdev !

  • No problem! Glad this helped. Good luck with your submission!

Add a Comment