Found this nice post about using Swift protocols to expose read-only properties of Core Data managed objects so you don’t couple your whole app to Core Data. Using Swift protocols in Core Data NSManagedObject
s is a great way to limit the visibility of properties and methods. In my 1st book on Mac app development I talked about this, too, and this is a lot easier to handle than a custom layer of struct
s that you have to map to NSManagedObject
and back again. Core Data is designed to be invasive and convenient. It’s not designed to be used as a simple object-relational mapper.
Continue reading …
In a post about the Swift reflection API, I found the conversion code from a Bookmark
struct to a Core Data object interesting. Let’s call the latter ManagedBookmark
.
What puzzles me: which object should be responsible for the adaptation from one to the other?
Bookmark
converts itself to a NSManagedObject
using a NSManagedObjectContext
you also have to pass in. (That’s what Benedikt did in his post.)
ManagedBookmark
provides an initializer or other factory taking in a Bookmark
and, as always with managed objects, a NSManagedObjectContext
.
Option 2 is pretty clear. Using Bookmark
s public interface, the managed object will set its attributes. This requires a NSManagedObject
subclass wheras option 1 can work with a dictionary of values.
My main worry is that in option 1 Bookmark
, a value type of the application, has to have knowledge about Core Data. Usually we’d fare better if we separate Core Data from our own model.
With extensions in Swift (and categories in Objective-C) we have the power to add new behavior to existing types in other locations. Does this help?
Extending a type in a different file hides that detail at first sight – but the extension, when it’s not private
, is available in the rest of the code base, too. It just appears as if you put the code in the type definition itself.
Now if Bookmark
is included in a “Bookmarking” module you import, an extension can add behavior without mixing Core Data visibly into the model layer. The Bookmarking module will not get altered when you extend one of its types in the client code.
I like organizing Swift code in modules because the boundaries are very strict. You cannot cheat yourself into mixing responsibilities and blurring boundaries that easily.
It seems the Unit of Work I envisioned is not the one I need. It seems Core Data calls NSManagedObjectContext
a “context” for a reason. It doesn’t suffice to set one up and pass it to every data store. At least not if you perform changes on background queues and with nested contexts.
Continue reading …
I ran into problems with my Core Data Unit of Work/Transaction implementation the other day. I was not exercising good NSManagedObjectContext
hygiene and end up with conflicts from time to time. Race conditions. Hate ‘em. The problem is that the parent–child setup of Core Data managed object contexts seems to work just fine for so-called “scratch pad” contexts: create a new child context, perform changes on in, then discard, or save to pass changes to the parent context.
Continue reading …
The Unit of Work pattern is a code equivalent to database transactions: when it completes, changes are persisted; when something fails, changes are rolled back. That’s handy to perform a set of changes and have them saved. Sooner or later during app development using Core Data, you may ask: when should I save? When is the best point in time?
Continue reading …
I created a generic CoreDataFetchRequest a while ago and love it. It casts the results to the expected values or throws an error if something went wrong, which it shouldn’t ever, logically – but the Core Data API currently returns AnyObject
everywhere, so I have to deal with that.
Continue reading …
It happens that just yesterday I read about architecture smells in code. Among the examples was “subclasses don’t redefine methods”. In my post about Core Data and expressive domains earlier this week, I did just that: create a Egg
subclass of CoreDataEgg
to inherit CoreDataEgg
’s behavior. That’s not what abstraction to superclasses is meant to do.
Continue reading …
I’ve written a whole book on the topic of architecting a Mac app using Core Data. Today I found an approach which doesn’t add lots of overhead and which also doesn’t clutter everything everywhere. It’s pretty simple and involves Swift.
Continue reading …
Swift 2 brings a lot of Cocoa API changes. For one, Core Data’s NSManagedObject
’s executeFetchRequest(_:)
can throw, returns a non-optional on success, but still returns [AnyObject]
. While refactoring existing code to use do-try-catch, I found the optional casting to [MyEntity]
cumbersome.
Continue reading …
Again I was reminded about the value of service objects to encapsulate sequences in two places: the Domain, where business rules are kept, and in client code, where database management and transactions play a role. This distinction helps create clean code and deliver flexible components. I am building a feature for the Word Counter in a separate “library” project until everything runs smoothly. Then I’ll integrate the code into the main application. Since I consider this to be some kind of library, I thought I wouldn’t need many service objects, but I was wrong.
Continue reading …
You don’t have to learn anything new if you work with Core Data in Swift. It’s a pain to use NSManagedObject
directly, so you better work with custom subclasses all the time. Unboxing optional NSNumber
s is just too cumbersome. There are caveats you should be aware of, though: Swift’s static typing makes it a bit harder to write test doubles for managed objects.
Continue reading …
I’m working on a way to make the Word Counter watch files and folders on a user’s disk. This will enable to measure project progress. Until now, I always used .plist
files to store records with the end in mind that I’m going to switch to a better alternative in the future. Since I’m adding all-new data tracking, I thought I might as well try different solutions now.
Continue reading …