Search code examples
ioscore-dataicloudcore-data-migration

Unexpected change of ubiquity store location after app update


Some preconditions: One of our apps is available in the App Store in version 1.2.0. We're using Core Data and iCloud. The options we give the NSPersistentStoreCoordinator are the following:

NSString *cloudContentName = [self cloudContentNameForStoreURL:cloudStoreURL];
NSURL *cloudStoreContentURL = [self URLForCloudContentForStoreURL:cloudStoreURL];
NSDictionary *cloudStoreOptions = @{
        NSPersistentStoreUbiquitousContentNameKey    : cloudContentName,
        NSPersistentStoreUbiquitousContentURLKey     : cloudStoreContentURL,
        NSMigratePersistentStoresAutomaticallyOption : @YES,
        NSInferMappingModelAutomaticallyOption       : @YES
    };

The store URL we choose is:

file:///private/var/mobile/Applications/F6819D1D-1935-487B-AA46-9FEE34275C02/Library/Application%20Support/CloudStore/F74FC85F-D3F6-4719-8ADC-B72570C9E7FE.sqlite

An app loaded from the App Store will then translate this URL and options to the following ubiquitous location and create a new store there:

file:///private/var/mobile/Applications/FAF62A03-2394-4133-9E84-DCB0BBEA1C22/Library/Application%20Support/CloudStore/CoreDataUbiquitySupport/mobile~36A5A006-FF08-4D16-B81B-DEAEE6D532F9/E5FBA065-8794-4C75-AEB5-C63004E1AAC6/7811DD75-3EEB-41A5-A748-C3206FBF9E31/store/E5FBA065-8794-4C75-AEB5-C63004E1AAC6.sqlite

Now to the problem: We've developed a new version of our app: 2.0.0. When our iPad has the App Store version of 1.2.0 installed and we're starting version 2.0.0 directly from Xcode, we can see that the Core Data framework translates our store options and URL not to the same, but a completely different URL:

file:///private/var/mobile/Applications/FAF62A03-2394-4133-9E84-DCB0BBEA1C22/Library/Application%20Support/CloudStore/CoreDataUbiquitySupport/mobile~3431F9C3-00D2-42D1-A888-9663B02F505E/E5FBA065-8794-4C75-AEB5-C63004E1AAC6/7811DD75-3EEB-41A5-A748-C3206FBF9E31/store/E5FBA065-8794-4C75-AEB5-C63004E1AAC6.sqlite

What you can see here is that the device's part of the ubiquitous URL has changed. This can be reproduced by us. It's always the same for the App Store version (/mobile~36A5A006-.../) and always the same for the debug version (/mobile~3431F9C3-.../). We noticed that it stays the same folder if we take version 1.2.0 not from the App Store but directly from Xcode/AdHoc distribution (even in Release configuration).

So we wonder what's going on there. Why does the framework try to load the store from a different folder (which does not exist)? It gives us an app without any existing data. We'd loose customer's data.


Solution

  • I've issued a TSI and got this answer:

    What you have seen (an Ad Hoc version uses a different path than the App Store version) is an expected behavior. The reason is that Core Data combined with iCloud uses the identifierForVendor of the app to create the store URL, and the identifier in App Store version and Ad Hoc version can be different. If you look at the specification of identifierForVendor in UIDevice class reference, you will see this: “… The value can also change when installing test builds using Xcode or when installing an app on a device using ad-hoc distribution.”

    The won't happen when you installing a update from App Store.