ios - update - core data xcode 8 objective c




Swift and CoreData/Data Storage (4)

All Objective-C frameworks are swift-ready. Swift-friendly headers are automatically generated (on-demand, it appears), and you can access anything from Swift that you can from ObjC.

I'm just learning Objective-C / Cocoa Touch and Core Data. So, what are the new possibilities to implement data storage in iOS App Projects that are written in pure Swift? I really like the language, but as far as I know all core data methods are written in Objective-C. So will the core data classes/methods converted to Swift-Code automatically or will we have to mix up Objective-C Code for Core data and Swift-Code for everything else?


Here is another approach to adding CoreData to your Swift app. This approach hides the CoreData implementation details from the rest of the app. In the app, you use queries/updates like these:

Query("Order").sort("date").fetch()

or:

let newClient = Query("Client").create() as? Client

See Gist: https://gist.github.com/gk11/438c3f2883c5d7c0b0d8


If you wanna have a play around with Swift and CoreData, I've written a framework thats an Active Record style assistant to CoreData.

SuperRecord Swift Framework

(note: not a shameless plug :) i actually thought this would be useful for the user).


This is how I implemented core data.

A couple of really important notes:

  • You have to add this to your NSManagedObject class:

    @objc(MyObject)

  • You have to add the entity name to your default configuration class in the .xcdatamodel (picture included)

  • You can't simply make an NSManagedObject.

    var myObject : MyObject = MyObject()

You have to do this:

let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let context: NSManagedObjectContext = appDelegate.managedObjectContext
let entityName: String = "MyObject"
let myEntityDescription = NSEntityDescription.entityForName(entityName, inManagedObjectContext: context)
var myObject = MyObject(entity: myEntityDescription, insertIntoManagedObjectContext: context)

Here is my NSManagedObject. I included two fetch methods as well as a class method for object construction. You may notice that I am taking advantage of the new enum system so that I can easily access my entity names and entity attributes

import UIKit
import CoreData

enum MyObjectPropertyList { 
    case name
    func description() -> String {
        switch self {
        case .name:
            return "name"
        }
    }
}

@objc(MyObject)
class MyObject: NSManagedObject {

    @NSManaged var name: String

    //
    //// CREATE CLASS OBJECT
    //

    class func createMyObject (propertyName:MyObjectPropertyList, value:String, context: NSManagedObjectContext) -> MyObject? {
        if !value.isEmpty {
            let propertyType = propertyName.description()

            let entityName = "MyObject"
            let request : NSFetchRequest = NSFetchRequest(entityName: entityName)
            request.returnsObjectsAsFaults = false
            request.predicate = NSPredicate(format: "\(propertyType) = %@", value)
            var error: NSError? = nil
            var matches: NSArray = context.executeFetchRequest(request, error: &error)

            if (matches.count > 1) {
                // handle error
                return matches[0] as? MyObject
            } else if matches.count ==  0 {
                let entityDescription = NSEntityDescription.entityForName(entityName, inManagedObjectContext: context)
                var myObject : MyObject = MyObject(entity: entityDescription, insertIntoManagedObjectContext: context)
                myObject.name = value
                return myObject
            }
            else {
                println(matches[0])
                return matches[0] as? MyObject
            }
        }
        return nil
    }
}

    //
    //// FETCH REQUESTS
    //

    func myGeneralFetchRequest (entity : CoreDataEntities,
                              property : MyObjectPropertyList,
                               context : NSManagedObjectContext) -> AnyObject[]?{

        let entityName = entity.description()
        let propertyName = property.description()

        let request :NSFetchRequest = NSFetchRequest(entityName: entityName)
        request.returnsObjectsAsFaults = false
        let sortDescriptor : NSSortDescriptor = NSSortDescriptor(key: propertyName, ascending: true)
        request.sortDescriptors = [sortDescriptor]
        var error: NSError? = nil
        var matches: NSArray = context.executeFetchRequest(request, error: &error)

        if matches.count > 0 {
            return matches
        }
        else {
            return nil
        }
    }

    func myNameFetchRequest (entity : CoreDataEntities,
                           property : MyObjectPropertyList,
                              value : String,
                            context : NSManagedObjectContext) -> AnyObject[]? {

        let entityName = entity.description()
        let propertyName = property.description()

        let request :NSFetchRequest = NSFetchRequest(entityName: entityName)
        request.returnsObjectsAsFaults = false
        request.predicate = NSPredicate(format: "\(propertyName) = %@", value)
        let sortDescriptor :NSSortDescriptor = NSSortDescriptor(key: propertyName, ascending: true)
        request.sortDescriptors = [sortDescriptor]
        var error: NSError? = nil
        var matches: NSArray = context.executeFetchRequest(request, error: &error)

        if matches.count > 0 {
            return matches
        }
        else {
            return nil
        }
    }

    //
    //// PRINT FETCH REQUEST
    //

    func printFetchedArrayList (myarray:AnyObject[]) {
        if myarray.count > 0 {
            println("Has \(myarray.count) object")
            for myobject : AnyObject in myarray {
                var anObject = myobject as MyObject
                var thename = anObject.name
                println(thename)
            }
        }
        else {
            println("empty fetch")
        }
    }

Here is my view controller

import UIKit
import CoreData

enum CoreDataEntities {
    case MyObject
    func description() -> String {
        switch self {
        case .MyObject:
            return "MyObject"
        }
    }
}

class ViewController: UIViewController {

    //
    //// MOC
    //

    var managedObjectContext : NSManagedObjectContext = NSManagedObjectContext()

    //
    //// Text Field
    //

    @IBOutlet var myTextField : UITextField

    //
    //// BUTTONS
    //

    @IBAction func saveButtonPress(sender : UIButton) {
        makeEntityAction()
    }

    @IBAction func fetchButtonPress(sender : UIButton) {
        fetchObjectAction()
    }

    //
    //// ACTIONS
    //

    func makeEntityAction () {
        println("-- Make action --")

        let value:String = self.myTextField.text
        var myObject : MyObject = MyObject.createMyObject(MyObjectPropertyList.name, value : value, context: self.managedObjectContext)!
        saveContext(self.managedObjectContext)
    }

    func fetchObjectAction () {
        println("-- Fetch action --")

        if let myTotalarray = myGeneralFetchRequest(CoreDataEntities.MyObject, MyObjectPropertyList.name, self.managedObjectContext) {
            printFetchedArrayList(myTotalarray)
        }
        if let mySinglearray: AnyObject[] = myNameFetchRequest(CoreDataEntities.MyObject, MyObjectPropertyList.name, "Bill", self.managedObjectContext) {
            println("(--  --)")
            printFetchedArrayList(mySinglearray)
        }

    }

    //
    //// LOAD & SAVE
    //

    func loadContext () {
        let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
        let context: NSManagedObjectContext = appDelegate.managedObjectContext
        self.managedObjectContext = context
    }

    func saveContext (context: NSManagedObjectContext) {
        var error: NSError? = nil
        context.save(&error)
    }

    //
    //// LOAD
    //

    func myLoad () {
        loadContext ()
        println("Loaded Context")
    }

    //
    //// Life Cycle
    //

    override func viewDidLoad() {
        super.viewDidLoad()
        myLoad ()
    }

}




swift