title: iCloud Core Data lightweight migration - entities disappear
body: <p>In my app, that is available on the Mac Appstore I have iCloud + Core Data integrated for Mavericks users. So I use the latest iCloud implementation, which wasn’t so buggy as the old one… I thought.</p>
  
  <p>Until now everything was fine, with the latest update of the app I made small changes to the Database, just adding a few new properties to an entity and created a new model version for this of course.</p>
  
  <p>If you start the updated version, all data is there and everything is fine. All entities are still there. This is the console output:</p>
  
  <pre><code>storesDidChange: {
      added =     (
          "&lt;NSSQLCore: 0x100410d10&gt; (URL: file:///Users/lars/Library/Containers/de.nulldesign.tyme.osx/Data/Library/Application%20Support/de.nulldesign.tyme/CoreDataUbiquitySupport/lars~053CB071-18DD-5ED8-B2F0-DD0341B523C7/iCloudStore/2B3578B9-3A28-492B-8C62-BFF7FE7076F3/store/TymeCloud.storedata)"
      );
  }
  
  -[PFUbiquitySwitchboardEntryMetadata setUseLocalStorage:](760): CoreData: Ubiquity:  lars~053CB071-18DD-5ED8-B2F0-DD0341B523C7:iCloudStore 
  Using local storage: 1
  </code></pre>
  
  <p>After a short while, this importer error occures:</p>
  
  <pre><code>__76-[_PFUbiquityRecordsImporter batchDownloadTransactionLogsAtLocations:error:]_block_invoke(763): CoreData: Ubiquity:  Librian returned a serious error for starting downloads Error Domain=LibrarianErrorDomain Code=1 "Der Vorgang konnte nicht abgeschlossen werden. (LibrarianErrorDomain-Fehler 1 - Unable to initiate download.)" UserInfo=0x600000271440 {NSDescription=Unable to initiate download., Item Errors={
      "file:///Users/lars/Library/Mobile%20Documents/HR22V4547K~de~nulldesign~tyme/CoreData/iCloudStore/lars~053CB071-18DD-5ED8-B2F0-DD0341B523C7/iCloudStore/16Dv7DuLeM4RoFUBtAVIQokfWJRwGABtWC81frFMCp0=/7B142E0C-3C97-4344-B647-28330E5D7FE3.1.cdt" = "Error Domain=UBErrorDomain Code=0 \"Der Vorgang konnte nicht abgeschlossen werden. (UBErrorDomain-Fehler 0 - Error Domain=UBErrorDomain Code=0 \"The operation couldn\U2019t be completed. (UBErrorDomain error 0.)\")\" 
  …
  UserInfo=0x600000271600 {NSDescription=Error Domain=UBErrorDomain Code=0 \"The operation couldn\U2019t be completed. (UBErrorDomain error 0.)\"}";
      };
      NSDescription = "Unable to initiate download.";
      NSUnderlyingError = "Error Domain=UBErrorDomain Code=0 \"Der Vorgang konnte nicht abgeschlossen werden. (UBErrorDomain-Fehler 0.)\"";
  }
  </code></pre>
  
  <p>Then a stores will change event fires:</p>
  
  <pre><code>storesWillChange: {
      NSPersistentStoreUbiquitousTransitionTypeKey = 4;
      added =     (
          "&lt;NSSQLCore: 0x100211490&gt; (URL: file:///Users/lars/Library/Containers/de.nulldesign.tyme.osx/Data/Library/Application%20Support/de.nulldesign.tyme/CoreDataUbiquitySupport/lars~053CB071-18DD-5ED8-B2F0-DD0341B523C7/iCloudStore/2B3578B9-3A28-492B-8C62-BFF7FE7076F3/store/TymeCloud.storedata)"
      );
      removed =     (
          "&lt;NSSQLCore: 0x100211490&gt; (URL: file:///Users/lars/Library/Containers/de.nulldesign.tyme.osx/Data/Library/Application%20Support/de.nulldesign.tyme/CoreDataUbiquitySupport/lars~053CB071-18DD-5ED8-B2F0-DD0341B523C7/iCloudStore/2B3578B9-3A28-492B-8C62-BFF7FE7076F3/store/TymeCloud.storedata)"
      );
  }
  </code></pre>
  
  <p>And quite a few storesWillChange &amp; storesDidChange shorty after:</p>
  
  <pre><code>storesDidChange: {
      removed =     (
          "&lt;NSSQLCore: 0x100410d10&gt; (URL: file:///Users/lars/Library/Containers/de.nulldesign.tyme.osx/Data/Library/Application%20Support/de.nulldesign.tyme/CoreDataUbiquitySupport/lars~053CB071-18DD-5ED8-B2F0-DD0341B523C7/iCloudStore/2B3578B9-3A28-492B-8C62-BFF7FE7076F3/store/TymeCloud.storedata)"
      );
  }
  -[PFUbiquitySetupAssistant tryToReplaceLocalStore:withStoreSideLoadedByImporter:](3250): CoreData: Ubiquity:  &lt;PFUbiquitySetupAssistant: 0x100411670&gt;
  
  Error refreshing peer range cache: (null)
  
  storesDidChange: {
      NSPersistentStoreUbiquitousTransitionTypeKey = 4;
      added =     (
          "&lt;NSSQLCore: 0x100410d10&gt; (URL: file:///Users/lars/Library/Containers/de.nulldesign.tyme.osx/Data/Library/Application%20Support/de.nulldesign.tyme/CoreDataUbiquitySupport/lars~053CB071-18DD-5ED8-B2F0-DD0341B523C7/iCloudStore/2B3578B9-3A28-492B-8C62-BFF7FE7076F3/store/TymeCloud.storedata)"
      );
      removed =     (
          "&lt;NSSQLCore: 0x100410d10&gt; (URL: file:///Users/lars/Library/Containers/de.nulldesign.tyme.osx/Data/Library/Application%20Support/de.nulldesign.tyme/CoreDataUbiquitySupport/lars~053CB071-18DD-5ED8-B2F0-DD0341B523C7/iCloudStore/2B3578B9-3A28-492B-8C62-BFF7FE7076F3/store/TymeCloud.storedata)"
      );
  }
  
  storesDidChange: {
      added =     (
          "&lt;NSSQLCore: 0x10020cdb0&gt; (URL: file:///Users/lars/Library/Containers/de.nulldesign.tyme.osx/Data/Library/Application%20Support/de.nulldesign.tyme/CoreDataUbiquitySupport/lars~053CB071-18DD-5ED8-B2F0-DD0341B523C7/iCloudStore/2B3578B9-3A28-492B-8C62-BFF7FE7076F3/store/TymeCloud.storedata)"
      );
  }
  
  -[PFUbiquitySwitchboardEntryMetadata setUseLocalStorage:](760): CoreData: Ubiquity:  lars~053CB071-18DD-5ED8-B2F0-DD0341B523C7:iCloudStore
  Using local storage: 1
  </code></pre>
  
  <p>After the store has changed, all entities are gone which were not created on this Mac. The other ones remain. Event if it switches to the cloud store:</p>
  
  <p>PFUbiquitySwitchboardEntryMetadata setUseLocalStorage: Using local storage: 0</p>
  
  <p>Only after upgrading all other Mac’s to the latest version of my app, the missing entities are getting synced back again.</p>
  
  <p>The documentation says: <strong>Changes to a store are recorded and preserved independently for each model version that is associated with a given NSPersistentStoreUbiquitousContentNameKey. A persistent store configured with a given NSPersistentStoreUbiquitousContentNameKey only syncs data with a store on another device data if the model versions match.</strong></p>
  
  <p><strong>If you migrate a persistent store configured with a NSPersistentStoreUbiquitousContentNameKey option to a new model version, the store’s history of changes originating from the current device will also be migrated and then merged with any other devices configured with that new model version</strong></p>
  
  <p>So I’m wondering, if this is an expected behavior when doing a lightweight migration in iCloud. For my users is definitively not an expected behavior, since their projects vanish until they have upgraded all their devices.</p>
  
  <p>The Core Data stack set up is pretty straight forward:</p>
  
  <pre><code>- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
  {
      if(_persistentStoreCoordinator)
      {
          return _persistentStoreCoordinator;
      }
  
      _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
  
      if(_iCloudConnectionPossible)
      {
          [[NSNotificationCenter defaultCenter] addObserver:self
                                                   selector:@selector(storesWillChange:)
                                                       name:NSPersistentStoreCoordinatorStoresWillChangeNotification
                                                     object:_persistentStoreCoordinator];
  
          [[NSNotificationCenter defaultCenter] addObserver:self
                                                   selector:@selector(persistentStoreDidImportUbiquitousContentChanges:)
                                                       name:NSPersistentStoreDidImportUbiquitousContentChangesNotification
                                                     object:_persistentStoreCoordinator];
      }
  
      [[NSNotificationCenter defaultCenter] addObserver:self
                                               selector:@selector(storesDidChange:)
                                                   name:NSPersistentStoreCoordinatorStoresDidChangeNotification
                                                 object:_persistentStoreCoordinator];
  
      NSURL *localStoragePath = [self dataStorePathUseiCloud:_useCloudStorage];
  
      NSError *error = nil;
  
      [_persistentStoreCoordinator lock];
      NSPersistentStore *persistentStore = [_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                                                                     configuration:nil
                                                                                               URL:storagePath
                                                                                           options:[self storeOptionsUseiCloud:_useCloudStorage]
                                                                                             error:&amp;error];
      [_persistentStoreCoordinator unlock];
      return _persistentStoreCoordinator;
  }
  
  - (NSDictionary *)storeOptionsUseiCloud:(BOOL)useiCloud
  {
      NSMutableDictionary *options = [NSMutableDictionary dictionary];
      [options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
      [options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];
  
      if(useiCloud)
      {
          [options setObject:@"iCloudStore" forKey:NSPersistentStoreUbiquitousContentNameKey];
      }
  
      return options;
  }
  
  - (NSManagedObjectContext *)managedObjectContext
  {
      if(_managedObjectContext)
      {
          return _managedObjectContext;
      }
  
      NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
  
      if(coordinator != nil)
      {
          NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
          moc.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;
  
          [moc performBlockAndWait:^
          {
              [moc setPersistentStoreCoordinator:coordinator];
          }];
  
          _managedObjectContext = moc;
      }
  
      [[NSNotificationCenter defaultCenter] addObserver:self
                                               selector:@selector(contextWillSaveNotification:)
                                                   name:NSManagedObjectContextWillSaveNotification
                                                 object:_managedObjectContext];
  
      [[NSNotificationCenter defaultCenter] addObserver:self
                                               selector:@selector(mergeChangesAfterDidSaveNotification:)
                                                   name:NSManagedObjectContextDidSaveNotification
                                                 object:_managedObjectContext];
  
      return _managedObjectContext;
  }
  </code></pre>
  
  <p>And the storesWill / DidChange handlers:</p>
  
  <pre><code>- (void)storesWillChange:(NSNotification *)note
  {
      NSManagedObjectContext *moc = self.managedObjectContext;
      [moc performBlockAndWait:^
      {
          NSError *error = nil;
          if([moc hasChanges])
          {
              [moc save:&amp;error];
          }
  
          [moc reset];
      }];
  }
  
  - (void)storesDidChange:(NSNotification *)note
  {
      // refresh UI, ...
  }
  </code></pre>
  
  <p>Is there any way around this? What’s wrong here?</p>