Recently, I saw a post from Dave DeLong and knowing his history with the framework I read it with extreme curiosity.
Unfortunately, that read led to this post as I disagree strongly with a number of the laws he has laid down.
Since I know people are going to be asking me about this post (I am still getting asked about Simmons’ post from a VERY long time ago), better to get my thoughts out now.
1. Do not use Core Data as if it were a database
No disagreement; Core Data is your object model and it can persist to a database but that is not its biggest strength.
2. Do not use Core Data as if it were a SQLite wrapper
This is re-iterating #1. Core Data is your object model, not a thin wrapper around a database.
NSManagedObjectContext is your “stack”
Here is where we start to disagree. The
NSManagedObjectContext is not your stack. It is a scratchpad. It is where you stage changes to the data objects and decide to persist them or not.
I have advocated putting an object around it for convenience and Apple added the
NSPersistentContainer which is designed to be subclassed. That wrapper is a great place to handle migrations, importing, exporting, convenience methods for accessing data; the list goes on.
All of the internal workings of your Core Data stack, your persistence and data model absolutely should be stored in the persistent container and that container should be injected through your controllers in your application.
4. Never ever ever ever ever use an
NSManagedObject outside its context’s queue
No disagreement. Core Data is designed to work in a threaded environment but most of the objects are NOT designed to work on multiple threads/queues. As with ANY object, assume it is thread locked unless you can demonstrably confirm that it is safe to use across threads.
5. Do not use
NSManagedObject as if it were an
NSManagedObject is an
NSObject that has additional functionality added. It should absolutely be treated as if it is an
NSObject because it is an
NSManagedObject instances are your data objects and should be treated as such. Creating Plain Old Objects on top of
NSManagedObject instances is asking for pain and data corruption.
6. You usually don’t need parent-child contexts
If you are not accessing the network, exporting data, importing data or interacting with the outside world in any way, shape or form then this is correct.
If your app talks to anything else then you will want to use parent-child contexts.
The parent context should be on the user interface thread (the main thread) and when you need to do asynchronous work with your data objects (importing or exporting) then you want to do that on another thread and that work should be done in a child context.
A child context simplifies the transfer of notifications of data changes and greatly simplifies using Core Data in a multi-threaded environment.
7. Keep your main queue context read-only
The main queue is also known as the user interface queue. The context that is associated with that queue should be for the user. That context reads and writes data when the user is interacting with the application.
Should it be read-only? Absolutely not.
Should it be user-only? Absolutely.
Any non-user work (importing and exporting) should be done on a child context on a background thread (see response to #6 above).
8. Use an abstraction layer
Please do not do this. You are going to make the next developer curse your name in a very unpleasant manner.
Use Core Data in your user interface. Do not create dummy data objects on top of Core Data. That leads to a maintenance nightmare.
Your user interface can use Core Data without really knowing that it is using Core Data. Your user interface treats the
NSManagedObject instances as if they were data objects because they are data objects.
Your user interface does not need to know any more about Core Data than it does for any other model structure. Your user interface should talk to your persistent container subclass and ask for the data it needs. The response to that request might be instances of
NSManagedObject or might be an
NSFetchedResultsController which then serves up the data objects in a consistent and reliable way.
9. Use Core Data as a local cache
I agree with the wording of this rule but I suspect the meaning is different. Core Data, like any local persistence, is a local cache of what is on the server. This is not specific to Core Data because that is what any local persistence does when you have data on a server.
Core Data is more than just a local cache.
Core Data is not complicated
Core Data is as complicated as you make it. Most of the time you do not need or want the advanced features of Core Data and can just grab an instance of
NSPersistentContainer and be happy.
When you need to deal with more complicated or interesting situations there is a fair chance that Core Data has an advanced feature to handle that situation. For the 80%, you can ignore those advanced features and relax in the comfort knowing they are there for if/when you need them.
The harder your code is to write the harder it is going to be to maintain and debug.
Don’t make it harder on yourself. Keep it simple.
After much consideration and review, I recently purchased a 2017 MacBook.
No, not a MacBook Pro 13 or 15. I purchased the 12 inch MacBook. The small laptop that people say over and over again cannot be used for development.
This is a living review of that MacBook as used by a macOS/iOS developer.
When Apple introduced the
NSURLSession API, the landscape of network operations changed. In some ways, the new API made things worse as the block API that was added tempts developers to become very sloppy with network calls. The block API makes it trivial to add network calls anywhere in an application. Very little thought or structure is required. From this (and some third party libraries who followed the same pattern) we have seen an explosion of increasingly poor network handling in applications.
For my own purposes I have resisted this slippery slope as often as possible. However I still preferred the way
NSURLConnection worked and how it integrated nicely with
NSOperation subclasses. My attempts at using the
NSURLSession were cumbersome and didn’t feel “right”.
Fortunately, I have recently worked on a design that I have been quite pleased with. In this design I am happily using
NSOperation subclasses again and I am using the
While at Empirical Development and then MartianCraft I had been distanced from all of the inventive solutions that other development teams have been coming up with for the past few years. I was living in a bubble of our development teams.
Now that I am working independently again, I am being exposed to a large number of interesting code bases.
It came as quite a surprise to me that view controllers are considered bad by many developers and that they have been coming up with some rather intersting solutions to make them more “manageable”.
To me, this is an indication that many developers have lost the perspective on what should and what should not be in a view controller. For some reason there is a misconception going around that everything belongs in the view controller.
Lets break it down.
It is time to move on to the next chapter.
What is Next?
Long term I have some ideas that will take a bit of time to put into place. In the short time I am eager to help as many teams as possible through short term contracting, consulting and workshops. I really do enjoy helping teams get the most out of their persistence and networking layers.
Effective immediately, I am available for short term and possibly long term contract work.
While I can assist with any form of iOS or OS X development, my area of expertise is in networking and persistence; specifically Core Data.
If you are not familiar with my experience, here are a few highlights:
- Wrote “The Book” on Core Data.
- Taught at universities around the United States
- Spoken at nearly every Apple related tech conference around the world
- Provided workshops on persistence, Core Data and Networking at many conferences and large corporations in and around the United States.
- Developed some of the most complex applications ever conceived for the iOS platform
What are the options?
I am looking for short term projects unless it is truly amazing, cutting edge, and never done before. I am looking to help your team provide a better experience for your users.
We can accomplish this either through a monthly, weekly, daily contract or through a workshop. The details of which we can discuss in detail. I am available to travel and can work on site for short periods of time.
Are you struggling with your persistence or networking layer?
Are you having performance issues that you are unable to isolate?
Would you like a fresh set of eyes on your project to get an idea of where things are?
Contact me; we can discuss the options.
Late last year I was contacted by the organizers of MCE Conf and was asked to speak. Since it fit within my schedule (which can be its own challenge these days) I accepted without thinking too much about it.
Shortly after my acceptance I had heard that there was some controversy surrounding the conference about a comment made by one of the organizers who had attended another conference. After reading up on the controversy I figured; “oh well, how bad can it be?”
The short answer? It was amazing. I absolutely loved every minute of the conference.
Whenever Apple releases a new version of Xcode one of the first things that I do is look at the default templates and see if there are any new or interesting things.
This year, with the release of Swift, there are some pretty radical changes. Yet the Core Data stack initialization code is still the same.
There is nothing wrong with the default template code but there isn’t really anything right about it either. It is far better than it once was but it is still overly verbose and hard to follow.
Therefore, I present my Swift Core Data stack code that I will be using as I grok this language.
I very rarely speak out against another blog post. I find the resulting argument back and forth draining. However, there are exceptions and one occurred over the weekend.
Brent Simmons has been blogging about his conversion of Vesper to a Core Data application. A recent post of his titled Core Data and Deleting Objects set my teeth on edge. Brent says:
“The best advice I’ve heard about deleting managed objects is to 1) not do it, or 2) do it only at startup, before any references to those to-be-deleted objects can be made.”
I do not know who is giving Brent advice but he must be playing tricks with him or just trying to wind him up. The advice was simple; don’t delete Core Data objects or if you are going to delete them, delete them at launch.
Will that work? Sure. Is it the right answer? Not even close.
Core Data has a number of features and abilities that are not commonly used. Chief among those are fetched properties. In discussing them with a number of developers, most have never heard of them and those who have heard of them couldn’t come up with a viable use case for them.
To be honest, I don’t have a lot of use cases for them myself. They are definitely not one of the core features of Core Data that I recommend people learning when they are initially getting comfortable with the framework.
In this article we will discuss one use case for fetched properties and the impacts.
## The Use Case
The use case for fetched properties that I have run across a few times comes into play when you have more than one persistent store file on disk. Imagine you are building a recipe application (one of my favorite examples). You decide to include a pre-built read-only database with existing recipes. However, your application has the ability to add notes and social comments to a recipe.
You want to keep the recipe database as read only (you have a separate one for new recipes) but you want the user to be able to add comments. Where do we put the data?
In this contrived situation, storing the comments (and other metadata) in another store makes sense. Unfortunately we can’t have relationships across physically separate stores.
Enter the Fetched Property.
## Fetched Property
A fetched property is a property added to a `NSManagedObject` entity that instead of storing a value or a relationship, it stores a `NSFetchRequest`. When the property is accessed for the first time the `NSFetchRequest` is fired and the results are returned.
A fetched property always returns a `NSArray` (well a subclass but that is a minor detail) and it can be configured to sort the results.
Unfortunately, the editor in Xcode does not permit adding sort criteria so the only way to add a sort to a fetched property is to create the fetched property in code. Hopefully that will be corrected in some future release of Xcode.
What does a fetched property look like? In the Core Data model editor, a fetched property is added just like an attribute or a relationship. Then in the Data Model inspector you can configure the `NSFetchRequest`.
The Destination is the entity that will be returned by the fetched property. The predicate is a string representation of the `NSPredicate` configured within the `NSFetchRequest`.
Further, the predicate can use one of two variables to help configure it:
`$FETCH_SOURCE` gets replaced by a reference to the entity that owns the fetched property. By using this variable we can reference properties in the owning entity.
`$FETCHED_PROPERTY` gets replaced by a reference to the the property description of the fetched property. The property description includes key value pairs that are accessible from within the predicate. I have not run across a situation where I have used this variable.
## The sharp edges
There are unfortunately some concerns with fetched properties.
Unlike a relationship, there is no way to pre-fetch a fetched property. Therefore, if you are going to fetch a large number of entities and then desire to access the fetched property for those properties, they are going to be fetched individually. This will drastically impact performance.
Fetched Properties are only fetched once per context without a reset. This means that if you add other objects that would qualify for the fetched property after the property has been fetched then they won’t be included if you call the fetched property again. To *reset* the fetched property requires a call to `-refreshObject:mergeChanges:`.
A fetched property always returns an array. While this is not a major issue if in fact you want more than one object returned. However, when that is not the case it is an additional method call that you need to make every time or add a convenience method. More code equals more bugs.
## To use or not to use
Fetched properties are not a main line piece of Core Data. It appears that even the Core Data team (or the Xcode team at least) agrees with that assessment based on how little effort is given to them in the model editor. Should you use them?
It depends. If you are joining two separate persistent stores and need a *soft* relationship between entities in those stores then yes, you can use them. They do work.
Be mindful of the edges, they are sharp.
Recently on [StackOverflow](http://stackoverflow.com) I have seen several questions regarding the desire for a parent Entity to be updated whenever an attribute within the child has changed.
There are several different ways to solve this problem. The easiest is to have the child ping the parent whenever it changes and then the parent can update any values it needs to as a result of that ping.
*Note: This is a re-print from the Mac Developer Network.*
One of the nice things about developing software for OS X is all the “freebies” we get out of Cocoa. For example, when we are building a UI with text input we get undo support for free! How cool is that?
Likewise, when we are working with Core Data, it also has undo support built right in. Every `NSManagedObjectContext` has a NSUndoManager that we can use. However there are some situations where the default undo support is insufficient.
In this article we are going to walk through one such situation.
*Note: This is a re-print from the Mac Developer Network.*
I tend to frequent the StackOverflow website and watch for questions about Core Data. Generally if it is a question I can answer I will and if it is a question I can’t answer then I really dig in for a fun session of exploration and attempt to find the answer.
When: November 2-4, 2011
Where: Los Angeles, CA
[Schedule and Additional Information](http://www.mactech.com/conference/about)
The speaker line up for MacTech this year is amazing. I am quite honored to be sharing the stage with such a group of people.
## What is MacTech Conference? ##
MacTech Conference is a 3-day, immersive, technical conference specifically designed for Apple developers, IT Pros, and Enterprise. “The whole idea of MacTech Conference is to allow members of the Apple community to meet and exchange ideas,” said Edward Marczak, Conference Chair and Executive Editor of MacTech Magazine. “This will be spurred on by presentations from some of the best and well-known experts in the community.”
MacTech Conference will have two separate tracks: one focused on programming / development, and the other on IT/Enterprise. Sessions will focus on both desktop and mobile, with appropriate levels of attention paid to the Mac, iPhone, iPad and iPod.
When: September 11-14, 2011
Where: Denver, Colorado
[Schedule and Additional Information](http://360idev.com/)
I am very pleased to announce that I will be speaking at this year’s 360 iDev conference in Denver, Colorado. Previously it was a foregone conclusion that I would be attending this conference since it was so close to my home. However, now that I am living in California, that is no longer the case.
However, I am happy to say that I will be attending this year despite a change in my home address. The speaker line up at 360 iDev keeps getting better each year and I am happy to be a part of this [great lineup](http://360idev.com/speakers).
If you are on the fence about going to this conference then please take my advice; GO.
Not only is the speaker line up great but Denver has a great walking downtown and the after session events should be just as entertaining as the speakers themselves.
I look forward to seeing you there.
When: September 5-7, 2011
Where: Brighton, UK
[Schedule and Additional Information](http://updateconf.com/)
I am very pleased to announce that I will be speaking in Brighton at the Update conference starting on September 5, 2011. The Update conference is a bit different than the normal “developer” conference that I attend and speak at. Instead of just or primarily focusing on the developer; a great deal of focus is put upon the user and the user experience. If you have been in attendance for any of Aral Balkan’s talks then you know very well what his focus is.
In addition to speaking at the conference I will be giving **two** one day workshops on Core Data. The first workshop will be an introduction to Core Data. I hesitate to call this a beginner workshop because *you*, the attendees, will be directing the workshop. If everyone wants to start at step one then we will. However throughout the day you will be setting the pace of what we learn and discuss. This format has worked very well in the past and the last time we did a workshop like this the day ended with some pretty advanced discussions.
The second session is labelled advanced and will be starting off with the assuming that we all know and understand the principals behind Core Data. In this session we will deep dive into some of the more complex areas of Core Data. Again, I have a list of topics but you, the attendees, drive the session. Therefore it is intentionally open ended so that you can come with your questions and problems and we can discuss them together. I plan on wrapping up the second workshop with some real world examples of edge cases and situations I have run into and how they were solved.
I invite you to join me in Brighton this September to attend Update 2011. I expect it to be a great time.