iCloud KVStore Entitlements Code Signing Error

I'm configuring a ```iCloud KVStore``` scenery with multiple apps. In this scenery you have a primary app that writes to its kvstore container, and secondary apps that read from the primary app's kvstore. The primary apps has a kvstore identifier that by defaults (when activating the ```iCloud Key-Value Store Capability```) is



<key>com.apple.developer.icloud-container-identifiers</key>

<array/>

<key>com.apple.developer.ubiquity-kvstore-identifier</key>

<string>$(TeamIdentifierPrefix)$(CFBundleIdentifier)</string>



As described by the common key-value store scenery for multiple apps in Apple's Doc:



Configuring Common Key-Value Storage for Multiple Apps



You have to specify for all the apps but the primary, the kv-store identifier of the primary, so like



<key>com.apple.developer.icloud-container-identifiers</key>

<array/>

<key>com.apple.developer.ubiquity-kvstore-identifier</key>

<string>ABCDEFGH.com.myCompany.myApp</string>



where



```ABCDEFGH.com.myCompany.myApp``` is the ```$(TeamIdentifierPrefix)$(CFBundleIdentifier)``` values.





While running the secondary app (that is a tvOS app in this case) it works if it has a default kv-store identifier, it does not run (it compiles), when using the requested ```ABCDEFGH.com.myCompany.myApp``` value, used to read the shared ```iCloud KVStore```



The error is:



> The entitlements specified in your application’s Code Signing

> Entitlements file do not match those specified in your provisioning

> profile. (0xE8008016).





I have also tried to check the Team-ID identifier's value, programmatically to be sure that is the one defined on the iTunesConnect portal like this:





+ (NSString *)bundleSeedID {

NSDictionary *query = [NSDictionary dictionaryWithObjectsAndKeys:

(__bridge NSString *)kSecClassGenericPassword, (__bridge NSString *)kSecClass,

@"bundleSeedID", kSecAttrAccount,

@"", kSecAttrService,

(id)kCFBooleanTrue, kSecReturnAttributes,

nil];

CFDictionaryRef result = nil;

OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&result);

if (status == errSecItemNotFound)

status = SecItemAdd((__bridge CFDictionaryRef)query, (CFTypeRef *)&result);

if (status != errSecSuccess)

return nil;

NSString *accessGroup = [(__bridge NSDictionary *)result objectForKey:(__bridge NSString *)kSecAttrAccessGroup];

NSArray *components = [accessGroup componentsSeparatedByString:@"."];

NSString *bundleSeedID = [[components objectEnumerator] nextObject];

CFRelease(result);

return bundleSeedID;

}



and in fact it is the right one:



```ABCDEFGH.com.myCompany.myApp```



I have tried an app that is on the AppStore already, and an app that is in development, but configured on the AppStore (so BundleID, Provisioning Profiles by this BundleID, all comes from iTunes Connect) but, the error stays on.

Replies

Same problem here.
I also tried to add
'ABCDEFGH.com.myCompany.myApp'
inside the array specified by
<key>com.apple.developer.icloud-container-identifiers</key>

but still not working and the error message is always the following


The entitlements specified in your application’s Code Signing

Entitlements file do not match those specified in your provisioning

profile. (0xE8008016).


Anyone can help?

I confirm that, even if I configure as you described:



<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-/
<plist version="1.0">
<dict>
<key>com.apple.developer.icloud-container-identifiers</key>
<array/>
<key>com.apple.developer.ubiquity-container-identifiers</key>
<string>$(MAINAPP_TEAMID)$(MAINAPP_BUNDLEID)</string>
<key>com.apple.developer.ubiquity-kvstore-identifier</key>
<string>$(TeamIdentifierPrefix)$(CFBundleIdentifier)</string>
</dict>
</plist>


I get the same very error.

<?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>com.apple.developer.icloud-container-identifiers</key>
    <array>
        <string>$(MAINAPP_TEAMID)$(MAINAPP_BUNDLEID)</string>
    </array>
    <key>com.apple.developer.ubiquity-kvstore-identifier</key>
    <string>$(TeamIdentifierPrefix)$(CFBundleIdentifier)</string>
</dict>
</plist>

Looking at the docs better,

the former solution is the correct one.

Apple's doc says:



  1. Designate one of your iCloud-enabled apps as the primary app.That app’s iCloud container becomes the common container. For example, in the case of a free and paid app, you might designate the paid app as the primary app.
  2. Enable the iCloud capability for each app.
  3. Enable the key-value storage option for both apps.Xcode automatically adds entitlements to each app and assigns an iCloud container based on the app’s bundle ID.
  4. For all but the primary app, change the iCloud container ID manually in the app’s
    .entitlements
    file.Set the value of the
    com.apple.developer.ubiquity-kvstore-identifier
    key to the ID of your primary app.



So this means that supposed to have $MAINAPP_TEAMID and $MAINAPP_BUNDLEID as app User-Defined settings, you have to put in the Entitlements:



<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-/
<plist version="1.0">
<dict>
<key>com.apple.developer.icloud-container-identifiers</key>
<array/>
<key>com.apple.developer.ubiquity-kvstore-identifier</key>
<string>$(MAINAPP_TEAMID)$(MAINAPP_BUNDLEID)</string>
</dict>
</plist>


The problem is that, XCode gives back always that error:


The entitlements specified in your application’s Code Signing Entitlements file do not match those specified in your provisioning profile. (0xE8008016).


What I don't understand here, is that, since the KeyValue Store is something automatic, you do not need to have a iCloud Container, so there is no no need to activate iCloudDrive. Anyways, suppose for a momento we want to have a iCloud Contanier as well:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-/
<plist version="1.0">
<dict>
<key>com.apple.developer.icloud-container-identifiers</key>
<array>
  <string>iCloud.$(CFBundleIdentifier)</string>
</array>
<key>com.apple.developer.icloud-services</key>
<array>
  <string>CloudKit</string>
</array>
<key>com.apple.developer.ubiquity-kvstore-identifier</key>
<string>$(MAINAPP_TEAMID)$(MAINAPP_BUNDLEID)</string>
</dict>
</plist>



At this point I have a iCloud Container and the KVStore from the main app. Anyways it does not work, XCode gives back the same error. But If I remove the main app kvstore-identifier, and so doing:



<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-/
<plist version="1.0">
<dict>
<key>com.apple.developer.icloud-container-identifiers</key>
<array>
  <string>iCloud.$(CFBundleIdentifier)</string>
</array>
<key>com.apple.developer.icloud-services</key>
<array>
  <string>CloudKit</string>
</array>
<key>com.apple.developer.ubiquity-kvstore-identifier</key>
<string>$(TeamIdentifierPrefix)$(CFBundleIdentifier)</string>
</dict>
</plist>


It runs without any issue, and it works even if I do not have any iCloud containers at all.

Plus, I can save items and read items to iCloid as easy as the following:



/*
Store item in the iCloud
@param service NSString The key to be stored
@param data id A <NSCoding> conformed object
*/
- (void)storeItem:(id)data key:(NSString *)key {
    NSUbiquitousKeyValueStore *cloudStore = [NSUbiquitousKeyValueStore defaultStore];
    [cloudStore setObject:data forKey:key];
    [cloudStore synchronize];
}
/*
Remove item in the iCloud
@param service NSString The item key to be removed
*/
- (void)removeItem:(NSString*)key {
    NSUbiquitousKeyValueStore *cloudStore = [NSUbiquitousKeyValueStore defaultStore];
    [cloudStore removeObjectForKey:key];
    [cloudStore synchronize];
}
/*
Retrieve item in the iCloud
@param service NSString The key to be retrieved
@return data id A <NSCoding> conformed object
*/
- (id)getItem:(NSString*)key {
    NSUbiquitousKeyValueStore *cloudStore = [NSUbiquitousKeyValueStore defaultStore];
    id data = [cloudStore objectForKey:key];
    return data;
}


But there is no way the share the main app container between this new app id. Why?


My three hypothesis so far:


  1. The main app team id is different from the secondary app team id. The reason is that the main app is an old app, when team id were different;
  2. The entitlements is misconfigured in some way;
  3. The App Identifier on iTunes Connect is misconfigured in some way;