yapstudios / YapDatabase

YapDB is a collection/key/value store with a plugin architecture. It's built atop sqlite, for Swift & objective-c developers.
Other
3.35k stars 365 forks source link

YapDatabaseRelationshipNode protocol causes strange crash in YapDatabaseCloudKitRecordHandler #382

Open uthiel opened 7 years ago

uthiel commented 7 years ago

Adding the <YapDatabaseRelationshipNode> protocol to one of my classes causes a crash in YapDatabaseCloudKitRecordHandler, which is more a less an exact copy of the CloudKitTodo example. The crash happens near the end of the block when the newly created CKRecord is populated with the properties of the database object:

        for (NSString *cloudKey in cloudKeys)
    {
        id cloudValue = [object cloudValueForCloudKey:cloudKey];
        [record setObject:cloudValue forKey:cloudKey];
    }

and the code tried to set the property superclass of the CKRecord to TSItem, which btw is the superclass of the object the block is handling. The resulting error message looks like this:

'Objects of class TSItem cannot be set on CKRecord'

Prior to conforming to <YapDatabaseRelationshipNode>, cloudKeys would look like this:

textData,
collectionUUID,
name

which are the properties of the class that are supposed to be synced with CloudKit, but after adding the protocol, cloudKeys suddenly looks like this:

hash,
superclass,
textData,
collectionUUID,
debugDescription,
description,
name

Does anyone know what's going on?

uthiel commented 7 years ago

I found out that yapDatabaseRelationshipEdges will get called although <YapDatabaseRelationshipNode> is commented out. While that doesn't cause a crash, it somehow messes up the database and makes objects vanish from the local cache, but strangely not from iCloud.

As soon as I activate <YapDatabaseRelationshipNode>, the app crashes on creating a new object, as explained above. Strange isn't it?

uthiel commented 7 years ago

I found the root cause of this crash:

In YapDatabaseRelationshipNode.h: @protocol YapDatabaseRelationshipNode <NSObject> Since iOS 8, @protocol NSObject declares some methods as properties:

hash,
superclass,
debugDescription,
description,

Conforming to the NSObject protocol makes class_copyPropertyList in MyDatabaseObject.m add those 4 properties.

Solution: In YapDatabaseRelationshipNode.h: change @protocol YapDatabaseRelationshipNode <NSObject> to @protocol YapDatabaseRelationshipNode

Do I need to issue a pull request for this?

uthiel commented 5 years ago

Can someone (maybe Robbie) please comment on why this issue hasn't been commented on yet?

robbiehanson commented 5 years ago

the code tried to set the property superclass of the CKRecord to TSItem

Haha. That's not going to work...

Since iOS 8, @protocol NSObject declares some methods as properties:

Oh wow. That's good to know. Great find !!!

Do I need to issue a pull request for this?

If you could that would be great. All 4 items in that list (hash, superclass, debugDescription, & description) should always be filtered from monitoring. We can probably filter this in MyDatabaseObject.m.