【问题标题】:Core Data Problems?核心数据问题?
【发布时间】:2015-05-20 11:38:24
【问题描述】:

我正在尝试使用CoreData,但我已经完成了我的项目的设置并且忘记选中该框以使用它。

如果在设置过程中之前没有选中CoreData 框,有没有办法实现核心数据的使用?

如果我开始一个新项目,则必须传输大量信息,这会很耗时,所以我想留在同一个项目上而不是创建一个新项目。

【问题讨论】:

  • 1.创建另一个项目,这次使用 Core Data。 2. 将 AppDelegate.swift 中的所有核心数据方法从新项目复制到旧项目中。不要忘记import CoreData 3.将xcdatamodeld文件复制到旧项目中。删除新项目。您现在已经将您的 Not-CoreData 项目变成了 CoreData 项目。 Xcodes 模板系统并没有做任何神奇的事情。如果你使用一个空的 Core Data 项目作为参考,那么很容易将 CoreData 添加到项目中。

标签: xcode swift core-data save


【解决方案1】:

坦率地说,您没有在项目创建时选中Use CoreData 框,这是正确的想法。我觉得这只是用一堆更容易(也更有洞察力)手动完成的东西使项目膨胀。

简而言之,无论您在项目创建时选择什么选项,都可以相同地实现 CoreData。

当我想(手动/以编程方式)向项目添加 CoreData 支持时,我通常会执行以下步骤:

定义数据模型

这些只是NSManagedObjects,代表您的应用程序的数据结构。比如UserMessageBlogPost等。我也为我的用户设置做了一个。

例子:

import CoreData

class User : NSManagedObject
{
    // @NSManaged is the replacement for @dynamic when using CoreData in Swift

    @NSManaged var identifier : String
    @NSManaged var firstName : String?
    @NSManaged var lastName : String?

    // This is called when a new User object is inserted to CoreData
    override func awakeFromInsert()
    {
        super.awakeFromInsert()
        self.identifier = NSUUID().UUIDString // generate a random unique ID
    }
}

添加核心数据模型

这是您通过以下方式添加到项目中的另一个文件:File -> New-> iOS-> CoreData -> Data Model。我通常将相同的xcmodeldata 文件存储在我的Models 项目文件夹中(连同我的实际模型类)。

选择这个新文件后,您将看到 CoreData 模型编辑器。您将希望看到右侧检查器窗格可见(热键是⌥⌘1)。对于核心数据编辑器,您还将主要使用第三个选项卡(数据模型检查器),该选项卡可通过 ⌥⌘3 进行切换。

现在您可以向这个数据模型添加一个实体对象(通过底部的Add Entity)。假设上面的例子,添加一个User 实体。选中User 实体后,添加上述类中定义的三个属性identifierfirstNamelastName。它们应该匹配类定义,使用String 类型。

下一步是告诉CoreData 这里定义的User 实体映射到我们实际的类文件。选中 User 并打开数据模型检查器窗格,将 Name 设置为 User 并将 Class 设置为 YourAppName.User

这是 Swift 和 CoreData 的“陷阱”,您的类以模块名称为前缀,以便为它们命名(避免名称冲突)。好的部分是您不再需要为您的对象添加“XYZ”类前缀。

初始化核心数据栈

定义好数据模型后,您需要初始化 CoreData 堆栈本身(数据库存储和上下文)。最基本的例子是你的NSManagedObjectContext 的全局单例,它会在需要时延迟加载。

你可以把它放在它自己的 Swift 文件中 (CoreDataStack.swift):

import CoreData

let managedObjectContext : NSManagedObjectContext =
{
    // This is your xcdatamodeld file
    let modelURL = NSBundle.mainBundle().URLForResource("MyApp", withExtension: "momd")
    let dataModel = NSManagedObjectModel(contentsOfURL: modelURL!)

    // This is where you are storing your SQLite database file
    let documentsDirectory : NSURL! = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).last as? NSURL
    let storeURL = documentsDirectory.URLByAppendingPathComponent("MyApp.sqlite")

    let psc = NSPersistentStoreCoordinator(managedObjectModel: dataModel!)

    var error : NSError?
    let store = psc.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storeURL, options: nil, error: &error)

    if let error = error
    {
        println("Uhoh, something happened! \(error), \(error.userInfo)")
    }

    let context = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)

    context.persistentStoreCoordinator = psc
    context.undoManager = nil

    return context
}()

使用核心数据

现在您已经有了一个工作的 Core Data 堆栈,定义和映射了一些数据模型……接下来呢?

让我们获取一些对象!

func getUsersByFirstName(firstName: String) -> [User]
{
    let fetchRequest = NSFetchRequest(entityName: "User")

    // The [c] part indicates case-insensitive, "Bob" == "bob"
    fetchRequest.predicate = NSPredicate(format: "firstName ==[c] %@", firstName)

    var error : NSError?
    let results = context.executeFetchRequest(fetchRequest, error: &error) as [User]

    // Handle errors here

    return results
}

哦,对了,我们没什么可取的。您还可以插入对象...

func insertNewUser() -> User
{
    return NSEntityDescription.insertNewObjectForEntityForName("User", inManagedObjectContext: context) as User
}

当然你也可以删除对象...

func deleteUser(user: User)
{
    context.deleteObject(user)
}

关键是要记住 CoreData 上下文 (NSManagedObjectContext) 会跟踪内存中的变化。虽然您可以在上下文中执行这些 CRUD 操作并立即查看更改(在同一上下文中),但在您保存更改之前它们不会保留在数据库中:

func saveContext() -> Bool
{
    var error : NSError?

    if context.hasChanges && !context.save(&error)
    {
        println("Something happened when saving! \(error!), \(error!.userInfo)")
        return false
    }

    return true
}

您还可以使用 context.rollback() 回滚上次保存的更改。

随意探索 CoreData 并尝试更高级的功能,例如谓词 (NSPredicate)、排序描述符 (NSSortDescriptor) 和设置对象关系。

【讨论】:

    【解决方案2】:

    基本上,Core Data 的所有复选框都是将核心数据框架 (CoreData.framework) 添加到您的项目中,并使用核心数据堆栈设置 AppDelegate.m,添加数据文件并可能为您提供示例视图控制器(取决于您开始使用的项目类型)。

    如果您希望像模板那样设置现有项目,那么最快的方法是创建一个新项目作为示例,然后选择 Core Data 复选框。打开新项目并查看 AppDelegate.m 文件并获取用于初始化核心数据堆栈的代码。它大约有 80 行,并且有一个注释调用了核心数据堆栈。

    将其转移到您现有的项目中,并将其放入您的 AppDelegate 文件中。同样在您现有的项目中,添加 CoreData.framework,然后在 Core Data 下添加一个新文件(文件->新文件->CoreData),称为“数据模型”文件。此文件用于定义数据模式的等效项。您选择它以使用图形控件。

    然后使用您的示例项目通过查看示例 ViewController 来查看您如何访问核心数据堆栈。

    注意:有些人不喜欢 Apple 如何在 AppDelegate.m 中设置 Core Data 堆栈,如果您搜索它,您会发现很多关于它以及如何做得更好的内容(我觉得有必要作出此免责声明)。 GitHub 上还有一些 3rd 方库也可以在这方面为您提供帮助。 (MagicalRecord、SLCoreDataStack 等)。

    希望有帮助! 好好的!

    【讨论】:

      猜你喜欢
      • 2011-07-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多