-
Notifications
You must be signed in to change notification settings - Fork 131
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Crash in persistentStoreEnsemble: globalIdentifiersForManagedObjects: - uniqueIdentifier - entity is not KeyValueCoding compliant #289
Comments
It looks like you probably don’t have a uniqueIdentifier property on all of your entities. You need to have something that identifies objects globally. If you do, the Ensembles can do all the import etc. So figure out if you already have such a property and return that in the delegate method. If not, see the model chapter of the book for strategies to introduce such a property in preexisting data. Kind regards, |
Thanks for the quick reply Drew.
I’ve been reading the book and holding off any changes I might make pending your reply.
I do not have a key that is “uniqueIdentifier”… but may have something else that will do the job… although it’s nothing like a UUID as per the text in your book.
Assuming I have something that might work… should I change the line of code
- (NSArray *)persistentStoreEnsemble:(CDEPersistentStoreEnsemble *)ensemble globalIdentifiersForManagedObjects:(NSArray *)objects
{
return [objects valueForKeyPath:@"uniqueIdentifier"];
}
to be
- (NSArray *)persistentStoreEnsemble:(CDEPersistentStoreEnsemble *)ensemble globalIdentifiersForManagedObjects:(NSArray *)objects
{
return [objects valueForKeyPath:@“myUniqueIdentifier"];
}
or do I have to have a field called uniqueIdentifier?
Also… regarding the uniqueIdentifier… if I follow the book it shows an example of UUID which is unique to the machine… but on it’s own it’s a duplicate with the next entry… what I’m asking is that that it doesn’t need to be UUID plus date/time to make it really really unique… if you see what I mean.
I have more questions.. about “Options” for the persistent store and how to “baseline”… but I don’t want to complicate this thread at the moment.
Thanks again for your fast reply.
- David
On 13/06/2020, at 10:03 PM, Drew McCormack ***@***.***> wrote:
It looks like you probably don’t have a uniqueIdentifier property on all of your entities. You need to have something that identifies objects globally. If you do, the Ensembles can do all the import etc.
So figure out if you already have such a property and return that in the delegate method. If not, see the model chapter of the book for strategies to introduce such a property in preexisting data.
Kind regards,
Drew
|
Yes, you can change the code to return whatever your unique id is. It doesn’t have to be called uniqueIdentifier
It is very important that the unique id of an object be unique, and be immutable. It can’t change. And the same object on different devices should have that same id, so they match up.
A creation date is a possible unique I’d, but there is a good chance it will collide with other ids, breaking the uniqueness requirement.
Kind regards,
Drew
… On 13 Jun 2020, at 12:15, David Wilson ***@***.***> wrote:
Thanks for the quick reply Drew.
I’ve been reading the book and holding off any changes I might make pending your reply.
I do not have a key that is “uniqueIdentifier”… but may have something else that will do the job… although it’s nothing like a UUID as per the text in your book.
Assuming I have something that might work… should I change the line of code
- (NSArray *)persistentStoreEnsemble:(CDEPersistentStoreEnsemble *)ensemble globalIdentifiersForManagedObjects:(NSArray *)objects
{
return [objects valueForKeyPath:@"uniqueIdentifier"];
}
to be
- (NSArray *)persistentStoreEnsemble:(CDEPersistentStoreEnsemble *)ensemble globalIdentifiersForManagedObjects:(NSArray *)objects
{
return [objects valueForKeyPath:@“myUniqueIdentifier"];
}
or do I have to have a field called uniqueIdentifier?
Also… regarding the uniqueIdentifier… if I follow the book it shows an example of UUID which is unique to the machine… but on it’s own it’s a duplicate with the next entry… what I’m asking is that that it doesn’t need to be UUID plus date/time to make it really really unique… if you see what I mean.
I have more questions.. about “Options” for the persistent store and how to “baseline”… but I don’t want to complicate this thread at the moment.
Thanks again for your fast reply.
- David
> On 13/06/2020, at 10:03 PM, Drew McCormack ***@***.***> wrote:
>
>
> It looks like you probably don’t have a uniqueIdentifier property on all of your entities. You need to have something that identifies objects globally. If you do, the Ensembles can do all the import etc.
>
> So figure out if you already have such a property and return that in the delegate method. If not, see the model chapter of the book for strategies to introduce such a property in preexisting data.
>
> Kind regards,
> Drew
>
David Wilson
http://dgwilson.wordpress.com
https://nz.linkedin.com/in/dgwilson65
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
Thank you for the feedback Drew.
I’ve done my updates and have read the section in the book on UUID and understand. I may make further changes but I get it.
New TOPIC if you will…
My existing macOS app and iOS app attempted to sync via iCloud.
Now with the installation of Ensemble do I turn off iCloud syncing? eeerrrr How?
I have this configuration for the persistentStore:
options = @{NSMigratePersistentStoresAutomaticallyOption: @yES, // Key to automatically attempt to migrate versioned stores
NSInferMappingModelAutomaticallyOption: @yES, // Key to attempt to create the mapping model automatically
NSPersistentStoreUbiquitousContentNameKey: @"TrafficCamNZ_DataStore", // Option to specify that a persistent store has a given name in ubiquity.
NSPersistentStoreUbiquitousContentURLKey: icloudURLForLogs // Option to specify the log path to use for ubiquitous content logs.
};
I had tried removing the UbiquitousContent keys… and ran into all sorts of issues.
- David
On 14/06/2020, at 1:52 AM, Drew McCormack ***@***.***> wrote:
Yes, you can change the code to return whatever your unique id is. It doesn’t have to be called uniqueIdentifier
It is very important that the unique id of an object be unique, and be immutable. It can’t change. And the same object on different devices should have that same id, so they match up.
A creation date is a possible unique I’d, but there is a good chance it will collide with other ids, breaking the uniqueness requirement.
Kind regards,
Drew
> On 13 Jun 2020, at 12:15, David Wilson ***@***.***> wrote:
>
>
> Thanks for the quick reply Drew.
>
> I’ve been reading the book and holding off any changes I might make pending your reply.
>
> I do not have a key that is “uniqueIdentifier”… but may have something else that will do the job… although it’s nothing like a UUID as per the text in your book.
> Assuming I have something that might work… should I change the line of code
>
> - (NSArray *)persistentStoreEnsemble:(CDEPersistentStoreEnsemble *)ensemble globalIdentifiersForManagedObjects:(NSArray *)objects
> {
> return [objects valueForKeyPath:@"uniqueIdentifier"];
> }
>
>
> to be
>
> - (NSArray *)persistentStoreEnsemble:(CDEPersistentStoreEnsemble *)ensemble globalIdentifiersForManagedObjects:(NSArray *)objects
> {
> return [objects valueForKeyPath:@“myUniqueIdentifier"];
> }
>
> or do I have to have a field called uniqueIdentifier?
>
> Also… regarding the uniqueIdentifier… if I follow the book it shows an example of UUID which is unique to the machine… but on it’s own it’s a duplicate with the next entry… what I’m asking is that that it doesn’t need to be UUID plus date/time to make it really really unique… if you see what I mean.
>
>
> I have more questions.. about “Options” for the persistent store and how to “baseline”… but I don’t want to complicate this thread at the moment.
>
> Thanks again for your fast reply.
>
> - David
>
> > On 13/06/2020, at 10:03 PM, Drew McCormack ***@***.***> wrote:
> >
> >
> > It looks like you probably don’t have a uniqueIdentifier property on all of your entities. You need to have something that identifies objects globally. If you do, the Ensembles can do all the import etc.
> >
> > So figure out if you already have such a property and return that in the delegate method. If not, see the model chapter of the book for strategies to introduce such a property in preexisting data.
> >
> > Kind regards,
> > Drew
> >
>
> David Wilson
> http://dgwilson.wordpress.com
> https://nz.linkedin.com/in/dgwilson65
>
> —
> You are receiving this because you commented.
> Reply to this email directly, view it on GitHub, or unsubscribe.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub <#289 (comment)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AABVCN6RLKPJDREG5TEJ7ODRWOABDANCNFSM4N4W4W6A>.
|
To "turn off" sync, simply don't call the leech or merge methods. Ensembles does not sync for you automatically. It is up to you to say when you want to sync. If you never call either of those methods, you will never sync. To remove the local cache of data and "detach" from the cloud, call the deleech method. If you want to remove all data, call deleech first, and in the completion handler, call the class method +removeEnsemble... passing in the file system object. Kind regards, |
Thanks again for your reply.
I wanted to know how to turn off the iCloud syncing I had implemented (the standard Apple one). I might be asking the wrong question here I don’t know.
… so I had implemented Apple’s iCloud syncing for CoreData - at least I thought I had
… and now I’ve implemented ensembles syncing
so I have now have 2 x sync’s running?
Hoping that question makes sense…
- David
… On 15/06/2020, at 7:14 PM, Drew McCormack ***@***.***> wrote:
To "turn off" sync, simply don't call the leech or merge methods. Ensembles does not sync for you automatically. It is up to you to say when you want to sync. If you never call either of those methods, you will never sync.
To remove the local cache of data and "detach" from the cloud, call the deleech method.
If you want to remove all data, call deleech first, and in the completion handler, call the class method +removeEnsemble... passing in the file system object.
Kind regards,
Drew
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub <#289 (comment)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AABVCN6JHSLR2TYBUDHOUETRWXC6PANCNFSM4N4W4W6A>.
|
Ensembles doesn't use or need any of the Apple Core Data sync. (Which one were you using: the old one or the new one from last year?) It could be that to stop using Apple's 'old' solution, you have to migrate your store. See this article, in particular under the heading (iCloud on/Off Switch). |
Hi Drew…
Good news. I've made progress. Thank you for your guidance.
A new issue has come up. I’m getting this error on iOS and macOS.
Thread 21: Exception: "Failed to process pending changes before save. The context is still dirty after 1000 attempts. Typically this recursive dirtying is caused by a bad validation method, -willSave, or notification handler."
I do have a willSave procedure in the main entity. Which I’ve also pasted below if it helps provide any clues as to what is going on.
- (void)willSave
{
[super willSave];
[self updateRecordUUID];
}
- (void)updateRecordUUID
{
// NSLog(@"%@", NSStringFromSelector(_cmd));
if (![self.recordUUID isEqualToString:self.url])
{
if (self.url)
{
[self willChangeValueForKey:@"recordUUID"];
[self setPrimitiveValue:self.url forKey:@"recordUUID"];
[self didChangeValueForKey:@"recordUUID"];
}
else
{
[self willChangeValueForKey:@"recordUUID"];
[self setPrimitiveValue:[[NSUUID UUID] UUIDString] forKey:@"recordUUID"];
[self didChangeValueForKey:@"recordUUID"];
}
}
}
- David
On 16/06/2020, at 8:09 PM, Drew McCormack ***@***.***> wrote:
Ensembles doesn't use or need any of the Apple Core Data sync. (Which one were you using: the old one or the new one from last year?)
It could be that to stop using Apple's 'old' solution, you have to migrate your store. See this article, in particular under the heading (iCloud on/Off Switch).
https://www.objc.io/issues/10-syncing-data/icloud-core-data/ <https://www.objc.io/issues/10-syncing-data/icloud-core-data/>
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub <#289 (comment)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AABVCNY7MKRNEDEYZPL7OKDRW4SDZANCNFSM4N4W4W6A>.
|
You could think about moving those earlier in the lifecycle, but if they are necessary, at least make sure each one is called just once. If you call a setter or fire KVO in willSave, it triggers a new save. This can go on forever. So you have to make sure that if you do this, the second call will go through without doing anything. No setter call or KVO. You can use an if to determine that.
Kind regards,
Drew
… On 21 Jun 2020, at 02:40, David Wilson ***@***.***> wrote:
Hi Drew…
Good news. I've made progress. Thank you for your guidance.
A new issue has come up. I’m getting this error on iOS and macOS.
Thread 21: Exception: "Failed to process pending changes before save. The context is still dirty after 1000 attempts. Typically this recursive dirtying is caused by a bad validation method, -willSave, or notification handler."
I do have a willSave procedure in the main entity. Which I’ve also pasted below if it helps provide any clues as to what is going on.
- (void)willSave
{
[super willSave];
[self updateRecordUUID];
}
- (void)updateRecordUUID
{
// NSLog(@"%@", NSStringFromSelector(_cmd));
if (![self.recordUUID isEqualToString:self.url])
{
if (self.url)
{
[self willChangeValueForKey:@"recordUUID"];
[self setPrimitiveValue:self.url forKey:@"recordUUID"];
[self didChangeValueForKey:@"recordUUID"];
}
else
{
[self willChangeValueForKey:@"recordUUID"];
[self setPrimitiveValue:[[NSUUID UUID] UUIDString] forKey:@"recordUUID"];
[self didChangeValueForKey:@"recordUUID"];
}
}
}
- David
> On 16/06/2020, at 8:09 PM, Drew McCormack ***@***.***> wrote:
>
>
> Ensembles doesn't use or need any of the Apple Core Data sync. (Which one were you using: the old one or the new one from last year?)
>
> It could be that to stop using Apple's 'old' solution, you have to migrate your store. See this article, in particular under the heading (iCloud on/Off Switch).
> https://www.objc.io/issues/10-syncing-data/icloud-core-data/ <https://www.objc.io/issues/10-syncing-data/icloud-core-data/>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub <#289 (comment)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AABVCNY7MKRNEDEYZPL7OKDRW4SDZANCNFSM4N4W4W6A>.
>
David Wilson
http://dgwilson.wordpress.com
https://nz.linkedin.com/in/dgwilson65
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
Thank you for the advice Drew.
I’ve modified the implementation so as not to invoke KVO and things are running under macOS and iOS and the changes are syncing.
I’ve also implemented a timer in both apps.
- (void)updateRecordUUIDWithUI:(BOOL)updateUI
{
if (![self.recordUUID isEqualToString:self.url])
{
if (self.url)
{
if (updateUI)
[self willChangeValueForKey:@"recordUUID"];
[self setPrimitiveValue:self.url forKey:@"recordUUID"];
if (updateUI)
[self didChangeValueForKey:@"recordUUID"];
}
else
{
if (updateUI)
[self willChangeValueForKey:@"recordUUID"];
[self setPrimitiveValue:[[NSUUID UUID] UUIDString] forKey:@"recordUUID"];
if (updateUI)
[self didChangeValueForKey:@"recordUUID"];
}
}
}
Hopefully you can use some of these questions and answers in your book.
- David
On 21/06/2020, at 8:27 PM, Drew McCormack ***@***.***> wrote:
You could think about moving those earlier in the lifecycle, but if they are necessary, at least make sure each one is called just once. If you call a setter or fire KVO in willSave, it triggers a new save. This can go on forever. So you have to make sure that if you do this, the second call will go through without doing anything. No setter call or KVO. You can use an if to determine that.
Kind regards,
Drew
> On 21 Jun 2020, at 02:40, David Wilson ***@***.***> wrote:
>
>
> Hi Drew…
>
> Good news. I've made progress. Thank you for your guidance.
>
> A new issue has come up. I’m getting this error on iOS and macOS.
>
> Thread 21: Exception: "Failed to process pending changes before save. The context is still dirty after 1000 attempts. Typically this recursive dirtying is caused by a bad validation method, -willSave, or notification handler."
>
> I do have a willSave procedure in the main entity. Which I’ve also pasted below if it helps provide any clues as to what is going on.
>
> - (void)willSave
> {
> [super willSave];
> [self updateRecordUUID];
> }
>
> - (void)updateRecordUUID
> {
> // NSLog(@"%@", NSStringFromSelector(_cmd));
> if (![self.recordUUID isEqualToString:self.url])
> {
> if (self.url)
> {
> [self willChangeValueForKey:@"recordUUID"];
> [self setPrimitiveValue:self.url forKey:@"recordUUID"];
> [self didChangeValueForKey:@"recordUUID"];
> }
> else
> {
> [self willChangeValueForKey:@"recordUUID"];
> [self setPrimitiveValue:[[NSUUID UUID] UUIDString] forKey:@"recordUUID"];
> [self didChangeValueForKey:@"recordUUID"];
> }
> }
> }
>
>
>
>
> - David
>
> > On 16/06/2020, at 8:09 PM, Drew McCormack ***@***.***> wrote:
> >
> >
> > Ensembles doesn't use or need any of the Apple Core Data sync. (Which one were you using: the old one or the new one from last year?)
> >
> > It could be that to stop using Apple's 'old' solution, you have to migrate your store. See this article, in particular under the heading (iCloud on/Off Switch).
> > https://www.objc.io/issues/10-syncing-data/icloud-core-data/ <https://www.objc.io/issues/10-syncing-data/icloud-core-data/>
> > —
> > You are receiving this because you authored the thread.
> > Reply to this email directly, view it on GitHub <#289 (comment)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AABVCNY7MKRNEDEYZPL7OKDRW4SDZANCNFSM4N4W4W6A>.
> >
>
> David Wilson
> http://dgwilson.wordpress.com
> https://nz.linkedin.com/in/dgwilson65
>
> —
> You are receiving this because you commented.
> Reply to this email directly, view it on GitHub, or unsubscribe.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub <#289 (comment)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AABVCN4YP5456D4XY3WBOT3RXXAAXANCNFSM4N4W4W6A>.
|
Hi Drew... Good news things seem to be going well... still in development between macOS and iOS (actual iPad and occasional simulator session). I did at one stage remove the iPad application and delete all the data (via the desktop application). The began with a fresh data import which also loaded UUID's as - [[NSUUID UUID] UUIDString] - for all rows. Now I'm getting new rows occasionally inserted... They have a UUID and the rest of the data is blank... How can I figure out where these are coming from and fix or prevent it?
|
Sounds like you perhaps changed the core data store (Eg deleted it) without deleeching.
Best to
- deleech
- remove cloud data using the CDEPersistentStoreEnsemble class method removeEnsemble...
- leech and merge
Kind regards,
Drew
… On 1 Aug 2020, at 09:55, David Wilson ***@***.***> wrote:
Hi Drew...
Good news things seem to be going well... still in development between macOS and iOS (actual iPad and occasional simulator session).
I did at one stage remove the iPad application and delete all the data (via the desktop application). The began with a fresh data import which also loaded UUID's as - [[NSUUID UUID] UUIDString] - for all rows.
Now I'm getting new rows occasionally inserted... They have a UUID and the rest of the data is blank...
How can I figure out where these are coming from and fix or prevent it?
David
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
Funny story... I did the coding for that last night for the macOS version... I'll see if I can get iOS done tonight - real life work has got in the way. If I've interpreted the instructions right... deleech on both (or all) devices... with 10 minutes and then initiate the leech and merge process. ohhh wait one... I haven't done this... "remove cloud data using the CDEPersistentStoreEnsemble class method removeEnsemble..." ... I'll add that. Thank you again for the assistance.
|
Good news. In my testing last night between macOS and iPadOS everything worked as it should have. Thank you again for the support. |
I have a macOS desktop app and an iOS app that I wish to sync the data between. They are apps that already existing their respective app stores. And I'm trying to switch to ensembles free.
In the macOS app I'm getting this crash (ensembles free was downloaded about the beginning of June 2020).
I think I've followed all of the instructions for integration... wouldn't surprise me if I missed something.
The crash will happen on first run, not on the second. Then crash on the 3rd (same crash point/error) and not on the forth.
Screenshot of the crash is below. Zombie objects is also enabled.
Ultimately I'm not sure if I should load my existing data and migrate to a new store? I'm don't know what the correct approach is. First thing is to get past this crash though.
The text was updated successfully, but these errors were encountered: