web-dev-qa-db-fra.com

Swift et CoreData/Stockage de données

Je viens d'apprendre Objective-C/Cocoa Touch et Core Data. Quelles sont donc les nouvelles possibilités d’implémentation du stockage de données dans les projets d’application iOS écrits en Swift pur? J'aime beaucoup le langage, mais autant que je sache, toutes les méthodes de données de base sont écrites en Objective-C. Ainsi, les classes/méthodes de données de base converties automatiquement en Swift-Code ou devrons-nous mélanger le code Objective-C pour les données de base et Swift-Code pour tout le reste? 

13
DanielAsking

Voici comment j'ai implémenté les données de base.

Quelques notes vraiment importantes:

  • Vous devez ajouter ceci à votre classe NSManagedObject:

    @objc (MyObject)

  • Vous devez ajouter le nom de l'entité à votre classe de configuration par défaut dans le fichier .xcdatamodel (image incluse).

xcdatamodel

  • Vous ne pouvez pas simplement créer un NSManagedObject.

    var myObject : MyObject = MyObject()
    

Tu dois faire ca:

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)

Voici mon NSManagedObject. J'ai inclus deux méthodes de récupération, ainsi qu'une méthode de classe pour la construction d'objet. Vous remarquerez peut-être que je profite du nouveau système Enum pour pouvoir accéder facilement à mes noms et attributs d'entité.

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")
        }
    }

Voici mon contrôleur de vue

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 ()
    }

}
21
MGM

Tous les frameworks Objective-C sont prêts pour Swift. Des en-têtes conviviaux pour Swift sont automatiquement générés (à la demande, semble-t-il) et vous pouvez accéder à tout ce que vous pouvez depuis Swift depuis ObjC.

9
Ben Gottlieb

J'avais testé l'utilisation de Swift pour accéder à Coredata, veuillez visiter le code de démonstration: https://github.com/iascchen/SwiftCoreDataSimpleDemo

3
IascCHEN

Si vous voulez jouer avec Swift et CoreData, j'ai écrit un cadre qui associe un assistant de style Active Record à CoreData. 

Cadre SuperRecord Swift

(note: pas une fiche éhontée :) j'ai en fait pensé que cela serait utile pour l'utilisateur).

1
mike.kz

XCode 6 Beta 4 vous permet maintenant de choisir Objective C ou Swift lorsque vous générez des sous-classes NSManagedObject à partir de votre modèle de données.

0
mcintst

Voici une autre approche permettant d’ajouter CoreData à votre application Swift . Cette approche masque les détails de la mise en œuvre de CoreData dans le reste de l’application. Dans l'application, vous utilisez des requêtes/mises à jour comme celles-ci:

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

ou:

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

Voir Gist: https://Gist.github.com/gk11/438c3f2883c5d7c0b0d8

0
GK100