Friday, January 31, 2014

YapDatabase

Robbie Hanson:

You cannot store a plain-old NSString in Core Data. It must be wrapped inside a NSManagedObject. Why? Because of the mandate above. An NSString is immutable. And Core Data wants to update the object you have in your hand, at the moment the context merges changes from another context. And it can’t change an immutable object. So it must wrap it inside something else, and change that.

[…]

This also has implications on threading. Why is it not safe to pass a NSManagedObject to background threads? Because that darn NSManagedObjectContext may mutate the thing at any time. So now threading becomes a nightmare. The fact is, the rules for NSManagedObject don’t follow the same rules you have for all other objects. Developers understand mutable vs immutable. Especially in objective-c where there are often 2 versions of a class, one mutable and one immutable. And developers understand the implications concerning threading: “Don’t be mutating something on one thread if it’s being used on another.” This is something we’ve lived with for a long time, and we’re quite adept at solving these problems. But NSManagedObject presents a whole new set of problems. We can’t just wrap one of these things in a lock, or only access it through a serial queue. Because NSManagedObjectContext isn’t going to follow our rules. It won’t play nicely, and so we’re forced to play entirely by its rules.

In contrast:

YapDatabase doesn’t use NSManagedObject, or any similar kind of silliness. You can store plain-old NSObjects. This includes your own NSObject subclasses, as well as the usual suspects such as NSString, NSNumber, UIColor, UIImage, etc. As long as the object can somehow be serialized & deserialized you’re good to go. This could be via NSCoding, or any other way you want such as JSON serialization. It’s completely configurable.

[…]

YapDatabase will never mutate any of your objects. Ever. This gives you complete control over your objects, and how & when you access and mutate them. You know, the way you’re used to dealing with objects.

YapDatabase looks really interesting. I skimmed the wiki to try to figure out the general architecture. It’s based on SQLite, which it uses as a collection-key-value store. In contrast to Core Data, it’s quasi-schemaless, although it does have some support for relationships.

It looks like there are four different mechanisms for selecting/filtering objects:

3 Comments RSS · Twitter

YapDatabase looks very interesting and promising.

> But NSManagedObject presents a whole new set of problems. We can’t just wrap one of these things in a lock, or only access it through a serial queue. Because NSManagedObjectContext isn’t going to follow our rules.

Not sure what is meant exactly by this, but maybe it's worth noting that you can use your own serial queue in CoreData (it does not have to be a specific thread or the queue provided by the context), as per Apple docs:

"Note: You can use threads, serial operation queues, or dispatch queues for concurrency. For the sake of conciseness, this article uses “thread” throughout to refer to any of these."

(See https://developer.apple.com/library/mac/documentation/cocoa/conceptual/coredata/articles/cdConcurrency.html)

@charles I’m not exactly sure what he meant there, but I agree with the general sentiment. Even if you wrap all of your accesses to the managed object with a block run on a particular queue, you can’t make the rest of Cocoa follow that pattern when accessing it. KVO is supposed to be one of the niceties of Core Data, and we pay for it by only operating on in-memory objects, but it makes threading messy.

[…] (2015-03-25): It looks like Fantastical 2 uses YapDatabase and SQLite’s FTS module for searching. I expect this means it will be immune to the many […]

Leave a Comment