iosbuild-settings

Flavouring Objective-C iOS app with Storyboard


I have a single-activity iOS app in Objective-C with Storyboard. The app has two build schemes, say Scheme 1 and Scheme 2. The View has just a couple of buttons. I want to differentiate the color of these button depending on the build scheme.

I am new in the iOS world, but I am having a hard time parametrising the Storyboard (e.g. colors, strings, etc.) depending on the build scheme. I am aware of this post, but I'd like something more explicit.

Thank you for your help.


Solution

  • Conditional compilation with Schemes isn't supported by Xcode. You'd need to maintain two targets instead for that, and that gets messy quickly.

    To do this with Schemes you need to maintain two asset catalogs with the correct named colors and copy the correct one in at build time. The source .xcasset catalogs would NOT be added to your target.

    You need to add a Run Script early on in the Build Phases section of your target.

    Luckily the Scheme name is expressed via the CONFIGURATION environment variable. You could do something like this, your paths might vary:

    # Copy over the appropriate asset catalog for the scheme
    target=${SRCROOT}/Resources/Colors.xcassets
    
    if [ "${CONFIGURATION}" = "Scheme 1" ]; then
    sourceassets=${PROJECT_DIR}/Scheme1.xcassets
    else
    sourceassets =${PROJECT_DIR}/Scheme2.xcassets
    fi
    
    if [ -e ${target} ]; then 
    echo "Assets: Purging ${target}"
    rm -rf ${target}
    fi
    
    echo "Assets: Copying source=${sourceassets} to destination=${target}"
    cp -r ${sourceassets} ${target}
    

    Essentially you are replacing the compiled version of the asset catalog with one of your Scheme specific versions.

    Strings would be another issue and you might be able to do this with the same technique for localised strings.

    This all gets horrible very quickly and isn't recommended. Configuring the UI at runtime via code using the technique described in your referenced post would be a better bet.

    You could construct a shim layer to protect your code from the Scheme changes.

    e.g

    @interface MyColors : NSObject
    
    + (UIColor *)buttonBackground;
    
    @end
    
    @implementation MyColors
    
    + (UIColor *)buttonBackground {
    
    #if SCHEME1
        return [UIColor colorNamed:@"scheme1ButtonBackground"];
    #else
        return [UIColor colorNamed:@"scheme2ButtonBackground"];
    #endif
    
    }
    
    @end