1 Reply
      Latest reply on Mar 13, 2020 8:56 AM by mikeyM
      mikeyM Level 1 Level 1 (0 points)

        I have a model that has already been pushed to production, and I would like to move an attribute to a new entity as a relationship.

         

        From This:

        extension Note {
          @NSManaged public var drawingData: Data?
          ....
        }
        
        

        To This:

        extension Note {
          @NSManaged public var drawing: Drawing?
          ....
        }
        
        extension Drawing {
          @NSManaged public var drawingData: Data?
          ....
        }

         

         

        According to the Apple Docs under the "Update your Production Schema" section, I will need to migrate to a new CloudKit Container, since we can't delete attributes on "production" CKRecords.

         

        What is the proper workflow to do this?

         

        I have come up with the following, but I believe it is wrong.

        lazy var oldPersistentContainer: NSPersistentCloudKitContainer = {
          let container = NSPersistentCloudKitContainer(name: "Model")
          let storeLocation = URL(fileURLWithPath: "/path/to/cloud.store")
          let storeDescription =
          NSPersistentStoreDescription(url: storeLocation)
          // Set the container options on the cloud store
          cloudStoreDescription.cloudKitContainerOptions = 
          NSPersistentCloudKitContainerOptions(
          containerIdentifier: "com.myCompany.myApp")
          container.loadPersistentStores...
          ...
        }()
        
        /// NOTE: - `containerIdentifier` has been "bumped"
        lazy var newPersistentContainer: NSPersistentCloudKitContainer = {
          let container = NSPersistentCloudKitContainer(name: "Model")
          let storeLocation = URL(fileURLWithPath: "/path/to/cloud.store")
          let storeDescription =
          NSPersistentStoreDescription(url: storeLocation)
          // Set the container options on the cloud store
          cloudStoreDescription.cloudKitContainerOptions = 
          NSPersistentCloudKitContainerOptions(
          containerIdentifier: "com.myCompany.myApp2")
        
          // TODO: Migrate Core Data Store if needed
          container.loadPersistentStores...
          ...
        }()

        NOTE: newPersistentContainer would have a "bumped" containerIdentifier and it would also perform Core Data Migration.

        Then I think I would need to manually move all records from oldPersistentContainer and add them to newPersistentContainer. Once all the data has been moved into the new container , I would delete all records from oldPersistentContainer. Would that be enough in terms of cleaning up oldPersistentContainer?

         

        It took me a while to come up with this workflow, but I still think it is wrong.  Could someone give me some insight on how to properly perform a CloudKit Container Migration with NSPersistentCloudKitContainer.

        • Re: NSPersistentCloudKitContainer "migrate to a completely new store"?
          mikeyM Level 1 Level 1 (0 points)

          So I believe I am overthinking it!

           

           

          lazy var persistentContainer: NSPersistentCloudKitContainer = {
              let container = NSPersistentCloudKitContainer(name: "Model")
              let storeLocation = URL(fileURLWithPath: "/path/to/cloud.store")
              let storeDescription = NSPersistentStoreDescription(url: storeLocation)
              //Set the container options
              cloudStoreDescription.cloudKitContainerOptions = 
                NSPersistentCloudKitContainerOptions(containerIdentifier: "com.myCompany.myApp2")
          
              // TODO: Migrate Core Data Store to new Model Version
              container.loadPersitentStores...
              ...
          }()
          
          

           

          This should be enough to handle the migration from Container 1 to 2, since the data is already stored in Core Data.  Then instead of hooking up a persistent container to the old CloudKit container (which would probably throw errors due to mismatched Schema), we can use CloudKit to fetch and confirm all data has already transfered properly, fix missing data, and delete the recrods in Container 1.

           

           

          I decided not to Migrate Containers for this, instead Im using "versioned entity" approach, but I just wanted to post this here in case it can help someone else.  If someone uses this approach, I'd love to hear your feedback whether it worked or not.