Xcode not copying latest resource file to iPhone

First of all: I feel your pain. I haven't found any good documentation on rolling up your sleeves and digging into the iOS build pipeline if you want to do some interesting (or even just simple) data pipelining using custom scripts.

Second of all: I don't agree that you need to, or even should put all your assets in your Xcode project. That's really a matter of personal preference, and if you've got a complicated enough project, Xcode becomes a beast to navigate your code alone as it is, let alone with all your art assets and data files.

Third: Cleaning is a work-around, as is touching an individual source-code file (Xcode will pick up on this and do the signing/touching of the master directory for you without the need to do a clean build -- a clean build is extremely time consuming if you have a large project or significant assets), but these are really just hacks to get the thing to work without fixing the underlying problem: you need to hit the right dependency to get the copy step to kick in.

I had the same issues you're describing here with the following differences: I'm using a gnu make script to process art resources (audio, data files, images) by doing some basic manipulations (compression, stripping out un-needed things, building fonts, etc). I'm using gnu make because 1.) I know it 2.) I find it easier to put all my rules into one script 3.) I like to keep my data folder nice and hierarchical and 4.) Xcode isn't always the way you want to interface/organize/manage all your data! (though I think it does a great job for code and even small amounts of data in a less complex project)

Anyhow, what I found is that I really had 2 problems: 1.) Code signing and 2.) Copying. The copying is easy, all you need to do is touch the build products folder. In my case I added the following to my make file: "touch $(DIR_CONTENTS)" where I defined "$(DIR_CONTENTS)" using the existing env parms provided by Xcode to the shell when my Xcode is executed: "DIR_CONTENTS = $(BUILT_PRODUCTS_DIR)/$(CONTENTS_FOLDER_PATH)" (you can see the full list of env parms if you click on the 3 horizontal lines in the output log). In your case you'd need to do the equivalent in your lua script. Not sure what that entails, I've been purposely dodging lua for years, but I can't imagine it's too crazy.

The next bit is trickier, 'cuz what I found was that just because you've updated, doesn't mean that the code signing stuff works nicely. In my case I needed to add a ResourceRules.plist file and add my art directory (art/.*) as a dictionary, with a line to omit and a weight. I couldn't find docs on this anywhere, so I copied the ResourceRules.plist file from the generated folder into my source folder, added it to the project, and then pointed the code signing stuff at it. (This would be in the build rules under Code Signing: it'll be your "Code Signing Resource Rules Path")

This isn't really my ideal solution, by the way. I would rather be able to trigger the code-signing step via my script if my data changes, but as I stated earlier I haven't found any useful docs in apple's developer library on how to really dig into the custom builds. You can do the code signing by hand, but I didn't like it.

Hope that helps.

UPDATE:

I figured I'd add some example code.... here are some relevant excerpts from my makefile:

# Near the beginning, where I do my variables n' such, I define the 
# directory in a variable. Note that BUILD_PRODUCTS_DIR and CONTENTS_FOLDER_PATH
# are environment variables set by XCode and will be filled with the corresponding
# paths
DIR_CONTENTS     = $(BUILT_PRODUCTS_DIR)/$(CONTENTS_FOLDER_PATH)
DIR_DEST_ART     = $(DIR_CONTENTS)/art
DIR_DEST_FONTS   = $(DIR_DEST_ART)/fonts
# ... more folders defined here...
DIR_SRC_FONTS    = $(SRCROOT)/source-art/fonts
# ... more folders defined here...

# ... do some useful build stuff ...

# This is an example of my rule that takes the .png's built by my font script
# and compresses them to .pvrs (note: this isn't final, so YMMV). The thing to
# note here is that if this rule kicks off, the last thing that will happen is
# that I will touch my DIR_CONTENTS folder, which will kick off the copy to the
# device. I find having to touch the folder really annoying, I prefer the way xcopy 
# and similar copy methods recursively travel & update if required.
$(DIR_DEST_FONTS)/%.pvr : $(DIR_SRC_FONTS)/%.png
    @echo == Compress $(subst $(SRCROOT),src,$<) to $(subst $(DIR_DEST_ART),dest,$@) ===
    @mkdir -p $(dir $@)
    @xcrun -sdk iphoneos texturetool -e PVRTC -o $@ -f PVR $<
    @touch $(DIR_CONTENTS)

Then, in order to deal with the code signing problem, I edited my ResourceRules.plist to look like the below. The area to pay attention to is the key that starts with "art/.*"

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>rules</key>
<dict>
    <key>.*</key>
    <true/>
    <key>art/.*</key>
    <dict>
        <key>omit</key>
        <true/>
        <key>weight</key>
        <integer>0</integer>
    </dict>
    <key>Info.plist</key>
    <dict>
        <key>omit</key>
        <true/>
        <key>weight</key>
        <real>10</real>
    </dict>
    <key>ResourceRules.plist</key>
    <dict>
        <key>omit</key>
        <true/>
        <key>weight</key>
        <real>100</real>
    </dict>
</dict>
</dict>
</plist>

You should definitely add those files to your Xcode project. You can still edit them in your other editor, but Xcode will include them in your bundle automatically if you add it to the project. If they aren't getting copied when you build, this is how I resolve it:

  • Right click on the file in Xcode and choose "Touch" which updates the timedate stamp on the file, so it looks "new".

  • On the simulator, choose Reset Content and Settings from the File Menu.

  • In Xcode, do a Build Clean

When you build and run after that it should install the file just fine.

EDIT:

To add external folders to your project that will get included in your bundle and preserve the folder structure intact, all you need to do is:

  • Click on the project icon at the top of the file list on the left.

  • Click the Project menu and Add to Project.

  • Select the folder you want to include and click Add.

  • Unchecked the Copy checkbox and change "Recursively create groups for any added folders" to "Create Folder References for any added folders".

  • When the target is built, open up the bundle and your directory structure will exist inside fully intact.

Tags:

Iphone

Xcode