ios Swift 和 CoreData / 数据存储

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24005342/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 00:16:19  来源:igfitidea点击:

Swift and CoreData / Data Storage

iosobjective-ccore-dataswift

提问by DanielAsking

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?

我只是在学习 Objective-C / Cocoa Touch 和 Core Data。那么,在纯 Swift 编写的 iOS 应用项目中实现数据存储有哪些新的可能性?我真的很喜欢这门语言,但据我所知,所有核心数据方法都是用 Objective-C 编写的。那么核心数据类/方法会自动转换为 Swift-Code 还是我们必须将用于 Core 数据的 Objective-C 代码和用于其他所有内容的 Swift-Code 混合在一起?

回答by MGM

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)

  • 你必须把它添加到你的 NSManagedObject 类中:

    @objc(MyObject)

  • 您必须将实体名称添加到 .xcdatamodel 中的默认配置类(包括图片)

xcdatamodel

数据模型

  • You can't simply make an NSManagedObject.

    var myObject : MyObject = MyObject()
    
  • 你不能简单地创建一个 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

这是我的 NSManagedObject。我包含了两个 fetch 方法以及一个用于对象构造的类方法。您可能会注意到我正在利用新的枚举系统,以便我可以轻松访问我的实体名称和实体属性

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

}

回答by Ben Gottlieb

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.

所有的 Objective-C 框架都是 swift-ready 的。Swift 友好的标头是自动生成的(按需,它出现),并且您可以从 Swift 访问任何您可以从 ObjC 访问的内容。

回答by IascCHEN

I had tested use swift to access coredata, please visit the demo code : https://github.com/iascchen/SwiftCoreDataSimpleDemo.

我测试过使用 swift 访问 coredata,请访问演示代码:https: //github.com/iascchen/SwiftCoreDataSimpleDemo

回答by mike.kz

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

如果您想玩转 Swift 和 CoreData,我已经编写了一个框架,它是 CoreData 的 Active Record 风格助手。

SuperRecord Swift Framework

SuperRecord Swift 框架

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

(注意:不是无耻的插件:)我实际上认为这对用户有用)。

回答by GK100

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:

这是将 CoreData 添加到 Swift 应用程序的另一种方法。这种方法对应用程序的其余部分隐藏了 CoreData 实现细节。在应用程序中,您可以使用以下查询/更新:

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

or:

或者:

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

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

见要点:https: //gist.github.com/gk11/438c3f2883c5d7c0b0d8

回答by mcintst

XCode 6 Beta 4 now lets you choose either Objective C or Swift when you generate NSManagedObject subclasses from your data model.

XCode 6 Beta 4 现在允许您在从数据模型生成 NSManagedObject 子类时选择 Objective C 或 Swift。