Latest

Sharing a Core Data Model with a Swift Framework

Updated on June 13, 2017 – Swift 3.0, Xcode 8

Code re-use is a powerful factor, nevertheless it’s not all the time straightforward to tug off. We attempt for it although, because in the long run, it makes maintaining the code far, far simpler than if we simply settled for copying and pasting.

With the introduction of dynamic frameworks in iOS eight, a world of risk opened up for iOS developers to realize some fairly cool re-use situations, one in every of which we’re going to dive into at present.

Not only can we share code between tasks, we will also share Core Data fashions between tasks by utilizing frameworks!

Maybe you’re engaged on an iOS + Mac app combination and the info model for each is equivalent. Perhaps you’re building several iOS apps which have totally different consumer interfaces however share some underlying persistence-layer fashions. Regardless of the case may be, wouldn’t it’s awesome to design the Core Data model as soon as and share it between your tasks?

Instance state of affairs

Our working instance for this walkthrough will be the following:

Our workforce is building an iOS app and a Mac app and the underlying knowledge model can be precisely the same between them. The only distinction between the apps would be the goal platform.

The app will goal automotive lovers all over the place – we’ll empower automotive fanatics to manage of a record of their favorite automobiles.

We’ll be creating two Xcode tasks during this walkthrough: One would be the framework and might be referred to as “CarKit”. The other can be a single view iOS software. We gained’t truly dive into the Mac challenge, but one might think about the method being very comparable for importing CarKit into the Mac software when it got here time to build that one.

I’m providing a accomplished CarKit + Carz package deal so that you can take a look at over at GitHub:

Let’s get began!

Creating a Swift framework challenge

To get started with creating a Swift framework, start with Xcode’s New Venture dialog (File -> New -> Undertaking…). Sometimes we stay within the realm of the “iOS Application” venture templates, however should you click “Framework & library”, you’ll see the option to create a new Cocoa Contact Framework:

In maintaining with Apple’s “___Kit” theme, we’ll identify our framework “CarKit”:
02 - Project Name

Add a knowledge model file

Once the framework challenge has been created, we’re set to drop in a new Data Model file from Xcode’s new file dialog (File -> New -> File…). Choose Core Data, after which Data Model:

03 - New File - Core Data - Data Model

Give the info model file a identify that appears to suit your state of affairs. For our instance, let’s identify it “CarModel”:
04 - Model Name

Add mannequin attributes

Next it’s time to truly add attributes to the model. Since our theme is automobiles here, we’ll stick with three easy attributes: yr, make, and mannequin:
05 - Complete Model

Create NSManagedObject subclass

With the mannequin attributes all configured, it’s time to create an NSManagedObject subclass. This can make consuming the model a lot easier in shopper purposes. I’ve truly written up a full walk via on creating an NSManagedObject subclass in Swift as there are some nuances. Be happy to learn up on that for those who so want!
06 - NSManagedObject Subclass

Be absolutely positive to mark your NSManagedObject subclass and its properties public – otherwise, the shopper app gained’t be capable of see the category or its properties:
061 - NSManagedObjectSubclass Public

As I point out in Implement NSManagedObject Subclass in Swift, it is advisable set the Module property within the Data Model Inspector to be CarKit (which is identical as the “Current Project Module” choice for this example):
07 - Change Entity Class

Build and examine outputs

We’ve obtained a framework, and we’ve received a Data Model with attributes and an NSManagedObject subclass all appropriately carried out. Now it’s time to build the venture and inspect the output of the construct!

Command + B to build, and then head up to the File menu and choose Undertaking Settings:
08 - Window - Projects

Within the Challenge Settings space that seems, click on the small grey arrow beneath the “Derived Data” section:
09 - CarKit - Projects Window

Next, find the derived knowledge folder on your undertaking. It ought to be named the same as your undertaking with a set of random characters after. Typically there might be multiple folders that could possibly be your venture. You possibly can take a look at the last modified date to assist figure you figure out which one was most lately constructed and choose that one.

Increase the Construct folder right down to Build -> Products -> Debug-iphonesimulator. There you must see the CarKit.framework artifact, and within it, every part that’s needed to be able to utilize the info mannequin in a shopper software. Awesome!
10 - CarKit - Finder - Includes momd

Observe: This framework isn’t production-ready. It’s a little extra involved to create a framework that one can run on a gadget / cross validation when submitting to the app store. The event of the framework stays the same, however the build phases and procedures have to be modified to make it “universal”. Slightly than overly complicate this walkthrough, I like to recommend reviewing “Universal Cocoa Contact Frameworks for iOS 8 – (Remix) by @kodmunki to create a “universal” framework capable of being run within the simulator and on iOS units.

Creating the framework-dependent app

With the framework built, it’s time to create the iOS app that may make the most of that framework and its packaged belongings! Begin a new challenge from File -> New -> Undertaking and choose “Single View Application”. I’ll identify our instance app “Carz”. Make sure that “Use Core Data” is selected so that you simply get the boilerplate Core Data code put into your undertaking by Xcode:
11 - New Single View App - Carz

Remove Xcode-generated .xcdatamodeld file

When you select “Use Core Data” within the venture creation window, Xcode routinely generates some boilerplate code, which we would like. Nevertheless it also provides us a “Carz.xcdatamodeld” file, which we won’t need as a result of we’ll use the model that’s found in CarKit. Remove the “Carz.xcdatamodeld” file that Xcode supplies for you:
12 - Remove default data model from new project

Acquire framework Bundle Identifier

Talking of utilizing the CarKit Core Data mannequin, we’re now ready to configure that piece of the app. To do that half, you’ll need to know the Bundle Identifier from your framework challenge. To seek out out what it is, bounce again over to the framework venture, click the top-level node within the venture navigator, click on on the framework goal identify, and look underneath the Basic tab of the venture configuration. There you’ll discover the Bundle Identifier, which you’ll be able to copy to your clipboard:
13 - CarKit Bundle Identifier

Exchange managedObjectModel property initialization

Out of the box, Xcode generates some code to help locate your Core Data model file. The boilerplate managedObjectModel property appears like this:

1
2
3
4
5

lazy var managedObjectModel: NSManagedObjectModel =
// The managed object model for the appliance. This property just isn’t optionally available. It is a deadly error for the appliance not to have the ability to discover and load its mannequin.
let modelURL = NSBundle.mainBundle().URLForResource(“DataModelFileName”, withExtension: “momd”)!
return NSManagedObjectModel(contentsOfURL: modelURL)!
()

Nevertheless, this gained’t work for us, as a result of we’re going to use the info model from CarKit, and CarKit is just not within the mainBundle(). For this reason we jumped over and copied the Bundle Identifier for CarKit in the earlier step. To find the info mannequin file in that bundle, you’ll substitute the managedObjectModel initialization step to the following (for CarKit):

1
2
3
four
5
6
7

lazy var managedObjectModel: NSManagedObjectModel =
// The managed object mannequin for the appliance. This property shouldn’t be non-compulsory. It is a fatal error for the appliance not to have the ability to discover and load its model.
let carKitBundle = Bundle(identifier: “com.andrewcbancroft.CarKit”)

let modelURL = carKitBundle!.url(forResource: “CarModel”, withExtension: “momd”)!
return NSManagedObjectModel(contentsOf: modelURL)!
()

16 - AppDelegate

Recall that “CarModel” is the identify of the Core Data mannequin we created for the framework in CarKit. We simply search for that artifact by calling URLForResource:withExtension: on the carKitBundle to initialize an NSManagedObjectModel instance.

Add CarKit framework to undertaking and embed binary

Now it’s time to truly deliver in the framework for use inside our app. I sometimes open up a Finder window and drag over a copy of the framework (on this case, the CarKit.framework file) into my venture. Be happy to arrange it into a “lib” folder.

Assuming that you simply undergo all the required steps to make the framework production-ready, you’ll need to embed the binary and make sure that it’s referenced within the “Linked Frameworks and Libraries” portion of your undertaking configuration:
15 - Embed CarKit and Link CarKit

Taking the mannequin out for a check drive (pun meant)

It’s easy enough to attempt issues out by writing a simple little snippet of code within the AppDelegate:

1
2
three
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

func software(_ software: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool
// Override level for personalisation after software launch.

let newCar = NSEntityDescription.insertNewObject(forEntityName: “Car”, into: self.managedObjectContext!) as! Automotive
newCar.yr = 2015
newCar.make = “Tesla”
newCar.model = “S”

do
attempt self.managedObjectContext?.save()
catch _

let fetchRequest = NSFetchRequest(entityName: “Car”)
let automobiles = (attempt! self.managedObjectContext?.fetch(fetchRequest)) as! [Car]

print(automobiles, terminator: “”)

return true

This code simply obtains a new Automotive object, units some properties, and saves it all with the managedObjectContext occasion that’s configured within the AppDelegate.

Then it goes and performs a fetch request to grab all the Automotive objects and prints them. The results? See for your self:
17 - Final Result

Wrapping up

This walkthrough guided you through the process of creating a framework for the aim of sharing a Core Data mannequin with multiple tasks. My hope is that you simply’re now empowered to make use of _re_use by using Swift frameworks to share even parts of your persistence layer!