23

My Xcode project is setup in a way that has multiple configurations, allowing me to use the same code base for different variations of my app, but have unique elements in each such as app name, version, bundle identifier, icon, launch screen, etc. I've followed this website in order to do most of the setup: http://appfoundry.be/blog/2014/07/04/Xcode-Env-Configuration/

I also have a config.plist containing various unique settings associated with each Xcode configuration that successfully only gets copied upon being built. Here's a snippet of the Run Script build phase in order to do that:

RESOURCE_PATH=${SRCROOT}/${PRODUCT_NAME}/config/${CONFIGURATION}

BUILD_APP_DIR=${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app

echo "Copying all files under ${RESOURCE_PATH} to ${BUILD_APP_DIR}"
cp -v "${RESOURCE_PATH}/"* "${BUILD_APP_DIR}/"

My next goal is to be able to copy a particular configuration's asset catalog when being built, so as to avoid bundling all of the different configuration's images into the build, causing it to become bloated. I've tried the same solution as above with the Run Script, changing the copy line to include the recursive option (since asset catalog is essentially a directory):

cp -rv "${RESOURCE_PATH}/"* "${BUILD_APP_DIR}/"

However, when I do this, my app fails to build and says it's unable to find the app icon and launch image. Any ideas?

Iulian Onofrei
  • 9,188
  • 10
  • 67
  • 113
codeman
  • 8,868
  • 13
  • 50
  • 79
  • Could you setup an example project in which you try to do this? I'm thinking of a few problems, but it all depends on how you setup your asset catalog(s) in your project. I'd be glad to help out, it's a very interesting idea! – Mike Seghers Feb 12 '15 at 08:25
  • In the meanwhile I've been investigating a bit. I could be mistaken, but if I look in my built packages, I only see the correct app icons included, and not the others. It seems that your issue actually is fixed by xcode mechanics under the hood. Could you verify? – Mike Seghers Feb 12 '15 at 14:32
  • Sorry for taking so long to respond. It's a bit hard to create a sample project. Not sure what you mean that Xcode actually fixes my problem. Could you explain? It fails to build complaining it can't find my launch screen and icon. Basically I have an asset catalog called images.xcasset for each configuration under a config folder. It gets copied just like config.plist. – codeman Feb 19 '15 at 21:11
  • I should mention I have to uncheck the target membership for the images.xcasset, just like config.plist. I suspect this is why Xcode doesnt find it when I try to build the app. – codeman Feb 19 '15 at 21:15
  • It sounds like what you really want is to have a project with multiple targets. [This article](http://www.reigndesign.com/blog/building-flockwork-creating-targets-for-free-and-full-versions-in-a-single-xcode-project/) is a very useful description of how that works. Having multiple targets allows you to specify the target that each asset catalog is included in, have multiple .plist files, etc. – Sarah Elan Feb 19 '15 at 21:55
  • That sounds like it could work. I was hoping to stay with multiple configurations instead of multiple targets since I've spent a good deal of time setting my project up like that. – codeman Feb 19 '15 at 22:18
  • I don't think you really need multiple targets. What we do is create two separate asset catalogs, which both are member of the application target. The first catalog holds the launch images and app icons. The second catalog holds all other assets. Xcode is smart enough (from what I see in the build .app package) to not include unnecessary app icons by it self. Is your problem only with app icons, or also other configuration specific assets? I will update the blog post with the info from this thread once we sort this out. – Mike Seghers Feb 20 '15 at 08:10
  • The problem is beyond just icons and launch screen images (although the launch screen images are pretty large in file size too). Other image assets unique to each configuration also take up a decent amount of file size. – codeman Feb 20 '15 at 14:44
  • Ok, now I get the entire problem. I'll investigate and report back. The problem is that assets are being compiled into .car files. So just copying the asset bundles won't do the trick. To be continued... – Mike Seghers Feb 20 '15 at 16:35
  • Exactly. Thanks for looking into it Mike. – codeman Feb 20 '15 at 16:40
  • i had a similar sounding issue where xcode mixed up the assets catalog configured for each target – Daij-Djan Feb 21 '15 at 12:57

1 Answers1

36

This is what you can do to make this work:

  • Add a separate asset catalog per configuration, just as you would normally add an asset catalog to your project. Let's assume for this example we call these catalogs MediaForDebug.xcassets, MediaForAdHoc.xcassets and MediaForRelease.xcassets
  • Make sure the newly created asset catalogs are all member of your target (so DO NOT exclude them here, we'll do that later on)
  • Now, if not already added to your build settings, add a custom EXCLUDED_SOURCE_FILE_NAMES User-Defined setting.
  • See the screenshot below for the values to be set for this User-Defined setting.

EXCLUDED_SOURCE_FILE_NAMES for config dependant asset catalogs

By doing this, Xcode will only compile the appropriate asset catalogs, and ignore the others. I've tested this on one of our projects, and it works as intended.

Good luck!

REMARK: If you are using CocoaPods, you might run into troubles because CocoaPods adds a build step of its own to compile your assets, and those of your dependencies into on .car file. See https://github.com/CocoaPods/CocoaPods/issues/1546 for the discussion on this issue. TL;DR: make sure this step doesn't execute in your build phase, or edit the CocoaPods script they execute to not do the asset building.

UPDATE 1/19/2019: With the latest stable Xcode (10.1) and Cocoapods (v1.5.3) they work out of the box with the solution above. No need to alter the Cocoapods scripts or build steps, just set EXCLUDED_SOURCE_FILE_NAMES as described.

jbelkins
  • 470
  • 3
  • 15
Mike Seghers
  • 1,925
  • 2
  • 16
  • 12
  • 12
    In case you have a lot of different configurations, the following might come in handy: EXCLUDED_SOURCE_FILE_NAMES = Media*.xcassets INCLUDED_SOURCE_FILE_NAMES = MediaForAdHoc.xcassets This way you don't have to exclude the assets one by one. – Damnum Apr 24 '16 at 06:54
  • "Add a separate asset catalog per configuration, just as you would normally add an asset catalog to your project." -- How do you add a separate asset catalog per configuration? – Chris Sep 15 '16 at 10:27
  • This solution is great but if you are using assets named to same then you will get a warning "The image set name xxx is used by multiple image sets" even though these errors don't represent the final state. Is there a workaround to this? – SmileBot Feb 15 '19 at 15:16