Building Your App Using Build Configurations and .xcconfig

Use Xcode build settings and .xcconfig files to change your app’s settings and icon with different build configurations. By Saleh Albuga.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 4 of 4 of this article. Click here to view the first page.

Using Configuration Files for Each Target

The app is now fully functional in all three environments. But what if you need to create or externalize a target-specific build setting for the WidgetExtention? Next, you’ll see how to create configuration files for the widget target.

In the Config files group, create the following configuration files:

  • WidgetBase.xcconfig:
    #include "Base.xcconfig"
    
    PRODUCT_BUNDLE_IDENTIFIER = $(BASE_BUNDLE_IDENTIFIER).widget
    
  • WidgetDebug.xcconfig:
    #include "Debug.xcconfig"
    #include "WidgetBase.xcconfig"
    
  • WidgetStaging.xcconfig:
    #include "Staging.xcconfig"
    #include "WidgetBase.xcconfig"
    
  • WidgetRelease.xcconfig:
    #include "Release.xcconfig"
    #include "WidgetBase.xcconfig"
    
#include "Base.xcconfig"

PRODUCT_BUNDLE_IDENTIFIER = $(BASE_BUNDLE_IDENTIFIER).widget
#include "Debug.xcconfig"
#include "WidgetBase.xcconfig"
#include "Staging.xcconfig"
#include "WidgetBase.xcconfig"
#include "Release.xcconfig"
#include "WidgetBase.xcconfig"

Here, you set the widget PRODUCT_BUNDLE_IDENTIFIER by appending BASE_BUNDLE_IDENTIFIER to your base setting.

Next, set the files to their respective environments for the WidgetExtension target in the Project Editor as below.

  • Debug
    • Project: Base
    • NinjaCounter: Debug
    • WidgetExtension: WidgetDebug
  • Staging
    • Project: Base
    • NinjaCounter: Staging
    • WidgetExtension: WidgetStaging
  • Release
    • Project: Base
    • NinjaCounter: Release
    • WidgetExtension: WidgetRelease
  • Project: Base
  • NinjaCounter: Debug
  • WidgetExtension: WidgetDebug
  • Project: Base
  • NinjaCounter: Staging
  • WidgetExtension: WidgetStaging
  • Project: Base
  • NinjaCounter: Release
  • WidgetExtension: WidgetRelease

Build configuration with custom widget configuration

Note: You don’t need to set WidgetBase.xcconfig because the other files include it.

Finally, return to the Project Editor and change the Product Bundle Extension setting for the WidgetExtension target to:

$(inherited)

After that, change the active scheme to WidgetExtension. Ensure the build configuration is Debug. Build and run.

Simulator showing the Widget. The Widget show the latest record added

The widget now shows the latest record you added for Donatello. Even though WidgetDebug.xcconfig doesn’t contain any settings, it includes the settings from WidgetBase.xcconfig and Debug.xcconfig. That’s why it worked when you set Debug.xcconfig for the widget.

Differentiating the App Icon for Non-Release Builds

Some stakeholders, like testers and QA engineers, use multiple builds of an app. For example, they might use the App Store build and a Staging build provided by developers or TestFlight. To make the lives of your colleagues easier, your next step will be to change the app icon to distinguish Debug and Staging builds from Release builds.

In the project, you’ll find another app icon set called AppIcon-NonProd in the app’s Assets.xcassets.

Assets catalog

To set the name of the asset catalog app icon set, you need to modify ASSETCATALOG_COMPILER_APPICON_NAME in the configuration files.

In Debug.xcconfig and Staging.xcconfig, add:

ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon-NonProd

In Release.xcconfig, add:

ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon
Note: As you’ve seen in the Project Editor’s Build Settings tab and in Info.plist, there are numerous build settings. You don’t have to remember the names of each one. Instead, use the build settings reference from the Apple documentation.

Set the active scheme to the NinjaCounter. Set the Build Configuration to Debug. Build and run. Enter the home screen.

iOS simulator home screen

The icon didn’t change because the Target Build Settings have higher precedence. To fix this, go to the Build Settings of NinjaCounter’s target from the project editor and locate Asset Catalog App Icon Set Name.

App build settings

In the configuration file’s scope, you can see the values you added to the configuration files. However, the setting resolves to the value at the target scope.

To fix this, change the parent value at the app target scope to $(inherited).

Changing build setting value to $(inherited)

The resolved values match the configuration files now.

Build and run. Enter the home screen.

iOS simulator home screen

The app now shows the icons from the AppIcon-NonProd app icon set.

Note: In the widget’s asset catalog, there’s an empty app icon set named AppIcon-NonProd. Although it’s not used, it solves a compile time error where Xcode will complain that AppIcon-NonProd doesn’t exist in widget’s asset catalog. This is because the widget target inherits ASSETCATALOG_COMPILER_APPICON_NAME from the app target and Xcode will check the value at compile time.

Where to Go From Here?

You can download the final project using the Download Materials button at the top or bottom of this tutorial.

In this tutorial, you used .xcconfig files to externalize build settings. You covered:

  • Managing settings across different build configurations.
  • Multiple approaches to using configuration files for different environments and targets.
  • Accessing build settings from code.

For more about build configuration and app distribution best practices, check out our iOS App Distribution & Best Practices book.

Here are some more helpful resources from Apple’s documentation:

I hope you’ve enjoyed this tutorial. If you have any questions or comments, please join the forum discussion below!