25

In my Xcode project, I have 4 different schemes (prod, dev, staging, staging2) which changes the bundle identifier of the app that gets installed to the phone. That way I can have all 4 versions installed side by side, similar to this technique.

Now I'm building a Today Extension for iOS 8. It's a new Target requiring its own bundle identifier.

The Extension's Bundle Identifier must be prefixed with the Parent App's Bundle Identifier, or a warning is thrown:

error: Embedded binary's bundle identifier is not prefixed with the parent app's bundle identifier.

    Embedded Binary Bundle Identifier:  com.company.app.TodayExtension
    Parent App Bundle Identifier:       com.company.app.staging

In this case, the Embedded Binary Bundle Identifier must be com.company.app.staging.TodayExtension.

Is there a way I can configure my Today Extension target to set its bundle identifier by first looking at the Parent target's bundle identifier? Perhaps through a custom Run Script Build Phase?

mfaani
  • 33,269
  • 19
  • 164
  • 293
djibouti33
  • 12,102
  • 9
  • 83
  • 116
  • 1
    Can you explain in more detail how you solved this problem? In Jafar's answer below, were you somehow able to set PARENT_APP_BUNDLE_IDENTIFIER just by switching schemes, and if so how? Or otherwise what did you specify for the bundle ids and PARENT_APP_BUNDLE_IDENTIFIER in each target (including the extension target)? Thanks! – qix Mar 15 '15 at 02:17
  • 5
    In Project Settings | Build Settings | User Defined, create a new entry called PARENT_APP_BUNDLE_ID. I have 4 configurations, I add a value for each one (com.company.app.staging, com.company.app.development, etc.). In you Main App Target's Info.plist, set Bundle Identifier to $(PARENT_APP_BUNDLE_ID). In your Extension Target's Info.plist, set it's Bundle Identifier to $(PARENT_APP_BUNDLE_ID).NameOfYourExtension. – djibouti33 Mar 16 '15 at 17:04
  • 2
    Aha, completely missed the fact that you were doing this through additional custom build configurations (Project | Info | Configurations) and setting a different value of PARENT_APP_BUNDLE_ID for each config at the Project level, instead thinking you somehow did it by overriding individual target settings. So you're still able to switch schemes to build w/ different bundle ids, since each scheme uses a different set of build configs. Cool, works for me, and helps me clean up duplicate targets and plist files! – qix Mar 16 '15 at 22:13
  • I'm so close! .. but how do I set "different value of PARENT_APP_BUNDLE_ID for each config at the Project level"?? – Doug Mead Oct 14 '16 at 19:21
  • 1
    when you add PARENT_APP_BUNDLE_ID to your build settings at the Project level, you should see all your configs underneath by clicking the triangle to the left. In my app, I have 4 configs (dev, prod, staging, staging2). After creating that user defined build setting, I see all 4 configs, and can assign each one a different value. – djibouti33 Oct 14 '16 at 20:19
  • 3
    what if my extension embedded to multiple targets? – Neil Galiaskarov Dec 18 '16 at 06:14

3 Answers3

33

The build settings of the targets are not available for the other targets. However the build settings of the PROJECT are available.

You can thus add a user-defined build setting in your project and call it PARENT_APP_BUNDLE_IDENTIFIER and set the correct bundle id for all your schemes.

Then in the info tab of the app extension target set the bundle id to

$(PARENT_APP_BUNDLE_IDENTIFIER).$(PRODUCT_NAME:rfc1034identifier)

It worked perfectly fine for me.

Alexis
  • 16,629
  • 17
  • 62
  • 107
  • Wonderful! This saves me so much frustration! – djibouti33 Sep 30 '14 at 19:27
  • 1
    am running same issue.. i followed above osolution... but not suceeded.. i have updated ios 8.0.2 and xcode 6.0.1(officila one) previiously i have 8.0 in that it worked fine for me.. – Sri Oct 20 '14 at 06:01
  • 3
    Please clarify this part: "set the correct bundle id for all your schemes" – Mirko Jul 19 '18 at 13:25
  • @djibouti33 did it really solve your problem? Seems to me that the PARENT_APP_BUNDLE_IDENTIFIER will be present independently in your extension's info.plist and get default values from the PROJECT's info.plist which can be useful when using different schemes but it still doesn't solve the problem if you are using different application targets, does it? – Kushal Ashok Feb 28 '19 at 13:40
  • 2
    Not work for me. `$(PRODUCT_BUNDLE_IDENTIFIER)` is defined by project and every target can set and read its value. In your app extension, you read the variable , you get and set itself. It does not make sense. – DawnSong May 18 '19 at 08:56
  • 1
    Alexis, following up the questions @Mirko and others have asked, does this solve the problem when you have different targets? Surely I can set a different bundleID for each configuration. But if I have 3 targets then how can I know which target is selected? Can you clarify that in your answer or possibly add screenshots? – mfaani May 29 '20 at 14:38
6

I have Siri extension and multiple targets, so to avoid duplicating extension for every target I added pre-action to every scheme that changes the BundleId of the extension's plist before build:

  1. Select 'Edit scheme'
  2. Click triangle near 'Build'
  3. Choose 'Pre-actions'
  4. Click '+', choose 'New Run Script Action'
  5. Choose target to provide build settings from
  6. In script field paste following with your BundleId and extension folder
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier 
YourDesiredBundleId" "$PROJECT_DIR/YourExtensionFolder/Info.plist"

And it works like a charm! You need to configure it for every scheme.

mfaani
  • 33,269
  • 19
  • 164
  • 293
Mike Makhovyk
  • 376
  • 3
  • 9
3

In my project I need to build different versions of apps (differ in details, e.g. each application is branded with a different logo).

Let's say there is about 10 "app" targets, I can't imagine adding Notification Content and Notification Service extensions per each main target (in this case I would maintaining 30 targets in total - madness).

I run a script (https://gist.github.com/damian-rzeszot/0b23ad87e5ab5d52aa15c095cbf43c59) after "Embed App Extensions" phase. It overrides bundle id in app extension plists and re-signs the bundle.

mfaani
  • 33,269
  • 19
  • 164
  • 293
Damian Rzeszot
  • 548
  • 3
  • 12