What’s new in Core Data Swift 3.0

Apple has made some big changes in Core Data and taken the burdens from our shoulders.
In this blog post we will be comparing Core Data with Xcode 7.3.1 vs new Core Data with Xcode 8 beta to see if it has become any easier to use Core Data.
If we are creating a new application with Single View Application or Master-Detail Application we can check the Use Core Data option and Xcode will automatically generate some boilerplate code in AppDelegate class. But what if you’re creating a Tabbed Application, Page- Based Application, Game, or even planning to add Core Data to an existing project? We can create a new Single View Application or Master-Detail Application and then copy all the code for core data from AppDelegate and paste it in our current project’s AppDelegate class. In both cases the AppDelegate class will be full with boilerplate code which are quite some lines of code.
An even better solution is to create a new class for the Core Data and put all the boilerplate code there. Then modify it as you wish, and you can use that class in all of your projects. Having a separate class will make your life easier in case you want to perform any kind of Migration in future releases of your app. Or even if you have an extension where both your container app and extension can access this class.
Here I Have created a class called CoreDataStack.swift and moved all the Core Data code from AppDelegate to CoreDataStack.swift

1. For Managed Object Model name Apple uses your application name by default but you can name it anything you like.
Keep in mind that you have to name your Data Model the same as your Managed Object Model for this example the name should be (Supercars.xcdatamodeld)

Ok now let’s see how do we use this class in AppDelegate.swift First we have to import core data.

Inside AppDelegate class we create a new lazy var instance of this class

However this blog post is not about Swift properties but you might be wondering why lazy var. we have seen lazy property in front of var many times now. Can we not just write the same line of code without lazy property like this

Actually we can, but lets see what Apple says about it and why it’s good to use it in this case.

A lazy stored property is a property whose value is not calculated until the first time it is used.

Ok enough talked about lazy property. Now let’s see how we can call save function in applicationWillTerminate function in AppDelegate class.

 

Now if we look at our AppDelegate class it’s a lot more clean and we can use CoreDataStack class in as many projects as we like.

But wait This post is not about refactoring we want to see what’s new in Core Data

I can say that Apple is try to tie our hands up and don’t want us to type a lot. Here is the same CoreDataStack class created in Xcode 8 beta and Swift 3 I think even a none programmer can see the big difference by counting lines of code in both classes.

Yes this is all the code in our new CoreDataStack class. You Create a persistentContainer it takes care of creating and loading your Managed Object Model. Everything is now encapsulated inside a single NSPersistentContainer class.

You may ask for few lines of code why I have created a class you can leave it in your AppDelegate class it’s totally fine. I think having it in a separate class will help you in the future for example if you want to make changes in your Data Model then you have to deal with Migration. Also your AppDelegate will be a few lines less and clean.

So is it all the changes in this new update for Core Data? The answer is NO.

let’s see how can we get an entity and add an item to it in current version of Core Data and Xcode 7.3 of course Swift 2.2

We can generate NSManagedObject subclass for our entity in that case the code will be like this

Generating NSManagedObject subclass for Entity is useful thing to do. It helps you eliminate key-value coding which can lead to any kind of mistyping, misspelling also gives you ability to use dot notation and so on. But you have to know that everything comes with a price. You have to generate NSManagedObject classes manually for your entities. Xcode will add 2 new files to your source tree per entity. Think if you have 5 entities then Xcode will add 10 new .swift files to your source tree not only that every time you make a change to any of your entity you have to regenerate your NSManagedObject subclass for that entity.

Now let’s see how can we get the entity and add an item to it in Xcode 8 and swift 3

That’s it. No more key-value coding, No more type casting, You don’t have to generate NSManagedObject subclasses yourself as soon as you add an entity to your Data Model build your project and Xcode 8 will happily take care of all those subclasses for you. Oh and your source tree will be clean as well.

I tried to quickly point a few important changes but there are a lot which has been changed. If you’re interested to know more watch WWDC 2016 What’s new in Core Data video.

https://developer.apple.com/videos/play/wwdc2016/242/

26 Comments

  1. Darko

    Thank you for this article, I thought that transition to swift 3 will be less jerky, but instead my app.delegate is in mess and so are all of my fetches, updates and saves.

    • Khalid Afridi

      Your right if your going to upgrade to swift 3 from swift 2.x then there will be some issues but for those who start new projects it’s getting much easer. There are a lot of functions have been renamed in swift 3 and some have been changed to calculated variables so you have to keep all those in mind if your upgrading your project to swift 3.

  2. .h
    @property (strong) NSMutableArray *devices;
    .m
    -(NSManagedObjectContext *)manangedObjectContext {

    NSManagedObjectContext *context = nil;
    id delegate = [[UIApplication sharedApplication] delegate];
    if([delegate performSelector : @selector (managedObjectContext)]){
    context = [delegate managedObjectContext];
    }
    return context;
    }

    – (void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];
    NSManagedObjectContext *managedObjectContext = [self manangedObjectContext];
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]initWithEntityName : @”Device”];
    self.devices = [[managedObjectContext executeFetchRequest:fetchRequest error:nil]mutableCopy];

    [self.tableView reloadData];
    }
    {
    NSManagedObjectModel *device = [self.devices objectAtIndex:indexPath.row];
    [cell.textLabel setText:[NSString stringWithFormat:@”%@ %@”,[device valueForKey:@”text1″],[device valueForKey:@”text2″]]];
    [cell.detailTextLabel setText:[device valueForKey:@”text3″]];
    }

    Addview
    .h
    @property (weak,nonatomic) IBOutlet UITextField *CarMake;
    @property (weak,nonatomic) IBOutlet UITextField *CarModel;
    @property (weak,nonatomic) IBOutlet UITextField *CarYear;

    @property (strong) NSManagedObjectContext *device;

    -(IBAction)DismissKeyboard:(id)sender;
    -(IBAction)SaveData:(id)sender;

    .m
    -(NSManagedObjectContext *) managedObjectContext {
    NSManagedObjectContext *context = nil;
    id delegate = [[UIApplication sharedApplication] delegate];
    if([delegate performSelector : @selector (managedObjectContext)]){
    context = [delegate managedObjectContext];
    }
    return context;
    }

    -(IBAction)DismissKeyboard:(id)sender{
    [self dismissViewControllerAnimated:YES completion:nil];
    }

    -(IBAction)SaveData:(id)sender {
    NSManagedObjectContext *context = [self managedObjectContext];
    NSManagedObject *newDevice = [NSEntityDescription insertNewObjectForEntityForName:@”Device” inManagedObjectContext:context];
    [newDevice setValue:self.CarMake.text forKey:@”text1″];
    [newDevice setValue:self.CarModel.text forKey:@”text2″];
    [newDevice setValue:self.CarYear.text forKey:@”text3″];

    NSError *error = nil;

    if(![context save:&error]) {
    NSLog(@”%@ %@”,error,[error localizedDescription]);
    }
    [self dismissViewControllerAnimated:YES completion:nil];

    }

  3. lakshmi

    HI,

    could you please provide sample example with core data in swift3

    • Khalid Afridi

      If you want a project the easiest will be to create a Master-detail Application by checking the use CoreData option. If you have some kind of specific question or needs help just point exactly there so I can help you with

  4. Hi!!
    I am trying to understand core data stack created in new Xcode 8 using swift 3 for os x application. Can I get help in understanding the same and using it to create managedObjectContext in my ViewController class.

    • Khalid Afridi

      Hi Kamal,
      The procedure is nearly identical what kind of help do you need? If I understand you well you can pass in the managedObjectContext from your delegate to your ViewController class. the other way around will be to make a CoredataStack singleton class where you can access your managedObjectContext through that singleton.

  5. qazal

    where should write below code ? I’m using Xcode 8 and swift 3
    let car = Car(context: context)
    car.name = “Ferrari”

  6. qazal

    Is there still a need to define the above codes?(core data stack codes)

    • Khalid Afridi

      Yes. if you start a project with Core Data checkmark checked then the code for Core Data will be automatically generated by Xcode in AppDelegate. for smaller projects that’s totally to leave it there.

  7. Ariane Clarke

    Hey! great article, well done :)
    I loved the changes! So easyyyy!!! a bit of a hassle to update old projects, but after updated, is sooo much better!

  8. JP

    If I have (swift 3) CordDataStack.swift Class, how to I write the Dependency Injection code for my masterVC class. I can’t get my head wrapped around it with the PScontainer?

  9. Chris

    Great article! However I am stuck on the last part.

    I added “import CoreData” and “lazy var coreDataStack = CoreDataStack()” to my AppDelegate. I set up the CoreDataStack class in its own Swift file and made the sure “NSPersistentContainer” name matched my xcdatamodeld file name. I set up the “Car” entity in my xcdatamodeld file, and set up an attribute “name” as the type “String”.

    But this part doesn’t work for me:
    let car = Car(context: context)
    car.name = “Ferrari”

    I get the errors:
    Use of unresolved identifier ‘Car’
    Use of unresolved identifier ‘context’

    Where have I gone wrong?

    • Khalid Afridi

      if you are accessing the context in your mainViewController then you have to pass the context from app delegate to any class that you want to access the context. also there is a bug in Xcode sometimes it’s not generating the managedObjectSubclass automatically but try to clean and build then it generate.

      • Ganesh

        Hi , how can I pass context from app delegate. If you don’t mind can you tell.

        • Khalid Afridi

          You have to get your ViewController in application: UIApplication, didFinishLaunchingWithOptions in delegate.swift and then you can pass your context to that viewController. if you don’t know who to get your view controller in appdelegate then there are a lot of tutorials available on how to do. hope it helps

          • Chris

            I tried clean and build but I get the same error, even when I try the “Ferrari” code in AppDelegate. But thanks for your explanation, it’s helping me to understand it a little better, although I’m still not having any luck.

            In your article you are calling coreDataStack.saveContext() but only in applicationWillTerminate() – when the app closes. So “use of unresolved identifier ‘context’” makes sense to me – my app doesn’t know what ‘context’ is, it hasn’t been defined.

            But even if I call coreDataStack.saveContext() before the Ferrari code to try and get ‘context’ defined, it doesn’t work…

            Could you post an example project to the article?

    • Ganesh

      Hi Chris,

      This is Ganesh. I also go the same issue, about context. How to create context. If you got the solution can you send please.

      Thanks

  10. atilla

    create post !
    i’m relatively new to swift, and still learning it
    if we use apple’s core data stack how about the concurrency stuff ? creating one context in main queue another in background queue and use them separately for UI and model, does new core data stack take care of it too ?

  11. Mohsin raza

    please suggest and guide me for ios development. now a fews days i am learning swift..like different framework coredata,coreanimation etc..

    • Khalid Afridi

      I am glad you want to learn iOS development.If your new then I would suggest you try the swift language it self maybe through Xcode’s playground because jumping toward different frameworks for the time being might confuse you. once you understand the swift language itself then using or learning other frameworks will become much easier. never give up you have started to learn then you can best of luck.

  12. Jessi

    Error handling now requires optional NSError, like so:
    if let error = error as NSError? {

Trackbacks for this post

  1. Core Data with Swift3.0 | UBUNIFU INCORPORATED
  2. Core Data for Swift 3 and iOS 10 Learning Notes | Yao Li — Programming, Reading, Running, Thinking, Traveling, Living

Leave a Reply