Codementor Events

CoreData and Data Persistence in iOS

Published Jun 11, 2019Last updated Dec 07, 2019
CoreData and Data Persistence in iOS

How important data persistance is! How would you be able to pick up where we left on that game, or finish that document you were working on? Being able to persist data is an essential function to almost every application. In this guide we are going to examine how to implement CoreData in iOS to create data persitance. I'll try to keep it brief and to the point so that it is easily understood. Lets begin!

Setting Up Your AppDelegate.swift

Before we start building our data model we'll need to add some code to our AppDelegate.swift file. Add the following code inside the AppDelegate class if you haven't done so already.

  // MARK: - Core Data stack
  
lazy var persistentContainer: NSPersistentContainer = {
        let container = NSPersistentContainer(name: "URLSchemeTest")
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        return container
    }()

    // MARK: - Core Data Saving support

    func saveContext () {
        let context = persistentContainer.viewContext
        if context.hasChanges {
            do {
                try context.save()
            } catch {
                let nserror = error as NSError
                fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
            }
        }
    }

Creating a Data Model

To begin building your data model, add a new file to xcode by clicking File > New > File... and then select Data Model. Give it a name like DataModel.xcdatamodeld.
Screen Shot 2019-04-28 at 5.05.52 PM.pngAdd a new file to your project by clicking File>New>File... and selecting Data Model

Screen Shot 2019-04-28 at 5.10.19 PM.pngGive the model an appropiate name.

CoreData comes with a GUI for designing you data model. Here is an example below of a object that stores a notification id and state. Your data model works similar to a standard class in Swift. The Entity is equivalent to a class. Attributes are equivalent to properties in a class. In CoreData, your datamodel defines the data object you want to save.
Screen Shot 2019-04-28 at 5.36.16 PM.pngIn CoreData, your datamodel defines the data object you want to save.

Name the entity and the attributes something that defines what they represent. In the above case, the entity is named "Notifications" and the attributes are named "notificationId" and "notificationState". Theses attributes will be what you save later. Now that we've defined our data model, lets get into some code.

Working With Your Data Model

The first step in working with your CoreData model is to create your NSManaged subclasses. I've shown the steps in the images below.
Screen Shot 2019-05-30 at 2.37.37 PM.pngStep 1. Have Xcode generate yout NSManaged subclasses.

Screen Shot 2019-05-30 at 2.41.10 PM.pngStep 2. Pick your data model.

Screen Shot 2019-05-30 at 2.41.25 PM.pngStep 3. Pick your entities you want to subclass.

Once you've created your subclasses you'll be left a couple .swift files that look like this.

import Foundation
import CoreData

@objc(Notifications)
public class Notifications: NSManagedObject {

}

import Foundation
import CoreData


extension Notifications {

    @nonobjc public class func notificationFetchRequest() -> NSFetchRequest<Notifications> {
        return NSFetchRequest<Notifications>(entityName: "Notifications")
    }

    @NSManaged public var notificationId: Int64
    @NSManaged public var notificationState: Bool

}

A small note about the file that contains the Notifications extention. I've altered the function name from fetchRequest() to notificationFetchRequest(). The generated code is initially fetchRequest, but it will fail to compile if you try to call the function. This is because the Notifications object is subclassed from NSManaged object, which already contains a function named fetchRequest(). Adding a function with the same name to the Notifications extention means there are now two functions named fetchRequest(). Why Apple would cause their generated code to do this is beyond me. So, rename your fetchRequest function in the extention. Hopefully this will save you some time tracking down that issue.

Loading and Saving To Your Model

I've included a class with this guide to show you how to work with the Notifications subclass that we've created.

import UIKit
import CoreData

class CoreDataNotifications{
    
    private static func setContext() -> NSManagedObjectContext {
        let appDelegate = UIApplication.shared.delegate as! SwiftAppDelegate
        let context = appDelegate.persistentContainer.viewContext
        return context
    }
    
    static func saveNewNotifications(newNotificationIds: [Int], newNotificationState: Bool){

        let context = setContext()
        for newId in newNotificationIds {
            let newNotification = Notifications(context: context)
            newNotification.notificationId = Int64(newId)
            newNotification.notificationState = newNotificationState
        }
        do
        {
            try context.save()
            print("Saved new notifications.")
        }
        catch { fatalError("Unable to save data.") }
    }
    
    static func loadWithCompletion(completion: @escaping ([Notifications]) -> Void) {
        
        let extractValues: [Notifications]
        let context = setContext()
        let request = Notifications.notificationFetchRequest()
        request.returnsObjectsAsFaults = false
        do
        {
            extractValues = try context.fetch(request)
        }
        catch { fatalError("Could not load Data") }
        completion(extractValues)
    }
}

Saving to Your Model

The steps to save and load are quite straight forward. First, you need to set your context. You can see this being done in the setContext() function which then returns the context to saveNewNotifications(newNotificationIds: [Int], newNotificationState: Bool). Next, you create a Notifications object using the context that you just recieved. Like this :
let newNotification = Notifications(context: context)
Once that has been done you can now set the properties of the Notifications object to a value. Like this: newNotification.notificationState = newNotificationState
These corespond to the attributes of the Entity defined in the CoreData model. Once that's done, all that's left is to call context.save. Make sure you enclose it in a do {} block like in the above class. You've now saved your first set of data to CoreData!

Loading From Your Model

Loading will feel pretty familiar after using the save function. The first step in loading is to set the context. Do this useing the same method as in the save function. Next, set your request using your Notifications object and your renamed fetchRequest function like this:
let request = Notifications.notificationFetchRequest()
Also, be sure to set the request.returnsObjectsAsFaults to true. If you don't, the load will return the records but not the value of the properties. You can read a little more about that in this Stackoverflow. Lastly set a varible that is of [Notification] type to the value of context.fetch(request). Like this: extractValues = try context.fetch(request). Be sure to enclose this in a do {} block as well. I added some completion logic to the the function to insure your applications recieves the loaded data before continuing to run. You can read more about completion in this post.

Conclusion

CoreData is a powerful and useful framework. This has shown the basics in setting up a CoreData model. If you enjoyed this post and would like to know more about CoreData, let me know what else you'd like to know about in the comments below. Thanks for reading!

Discover and read more posts from Franco Fantillo
get started
post commentsBe the first to share your opinion
JainJude
5 years ago

3D TouchSo about the current state of 3D Touch.

So far with the iOS 13 Betas 3D Touch has been all but replaced with haptic touch on stock Apple apps. This has seemingly been somewhat “fixed” in beta 3 where the display actually feels like it registers how hard you press on the screen but it is still 90% haptic touch. Was this the fix to the “bug” Apple referred to? Or will we actually see a complete return to iOS 12 era 3D Touch?

Although Apple has addressed this as a bug (back on the 1st and 2nd betas) and that the final iOS 13 would bring back 3D Touch, there have been some pretty substantial rumours that Apple might phase out 3D Touch in favour of haptic touch for future iPhones. This could even apply to older gen iPhones with the ‘part 3D Touch/part haptic touch’ we are seeing in beta 3. https://ixxx.onl/

So, as a summary, is the beta 3 version of haptic/3D touch what Apple is going for? Or will OG 3D Touch fully return when the final version is out? What will this mean if iPhone 2019 is fully haptic touch? Will Apple really release a product that has a “inferior?” Version of a feature? Or will Apple remove 3D Touch from all previous iPhones to balance out the lineup? https://xvideos.onl/ https://xnxx.onl/

Show more replies