gpt4 book ai didi

ios - Swift CoreData 编辑/更新实体,当它只有 1 个实例时

转载 作者:搜寻专家 更新时间:2023-11-01 06:09:06 25 4
gpt4 key购买 nike

这个问题似乎已经被问了很多了。但我一直无法找到快速的解决方案。

我有一个名为“用户”的实体,应该只有一个。所以在它第一次被创建之后。我需要编辑/更新它的值而不是创建更多值。

我确实在 youtube 上找到了它的视频。这是下面提供的尝试。但是它不起作用。

这是我在 viewDidLoad() 之前的 viewController 类中的代码

// Core data setup
let context = (UIApplication.sharedApplication().delegate as AppDelegate).managedObjectContext!
var newUser : User? = nil
var results = NSArray()

var hasAccount = Bool()

这是我在 viewDidLoad()

中的代码

println(新用户)

    // Core data fetching
var request = NSFetchRequest(entityName: "User")
request.returnsObjectsAsFaults = false
results = context.executeFetchRequest(request, error: nil)!
if results.count > 0 {
hasAccount = true
var res = results[0] as NSManagedObject
println(res.valueForKeyPath("email")!)
}
else {
println("No Account")
}

我使用上面的代码来确定 User 实体中是否已经存在某些内容(然后将 hasAccount 设置为“true”)。但是,如果您碰巧知道执行此操作的更好方法。将不胜感激!

我打印了“newUser”,希望能打印出 User 对象。所以我可以检查 if newUser != nil { do this } 但是我在上述解决方法之外尝试获取“用户”的所有尝试都失败了。

现在我无法以任何方式开始工作的代码是这样的:

let ent = NSEntityDescription.entityForName("User", inManagedObjectContext: context)

if hasAccount == false {
println("Creating a new User Object")
let newUser = User(entity: ent!, insertIntoManagedObjectContext: context)
newUser.firstName = firstNameTextField.text
newUser.lastName = lastNameTextField.text
newUser.email = emailTextField.text
newUser.password = passwordTextField.text
newUser.accountType = 0
context.save(nil)
} else {
println("Updating existing User Object")
newUser?.firstName = firstNameTextField.text
newUser?.lastName = lastNameTextField.text
newUser?.email = emailTextField.text
newUser?.password = passwordTextField.text
newUser?.accountType = 0
context.save(nil)
}
println(newUser)

创建新用户对象的部分。应该管用。 (但是未经测试,因为我将它移到了 if 语句中)

但是应该更新实体的部分不起作用。我知道它运行是由于 println

但它不会更改用户实体。

如有任何帮助,我们将不胜感激!

最佳答案

首先让我说 Core Data 是一个非常强大的框架,用于持久化和维护对象图。话虽如此,不幸的是,它确实需要大量的努力才能开始。出于这个特殊原因,我通常建议初学者查看 MagicalRecord .这是一个令人愉快的库,它删除了设置堆栈以及维护和创建上下文所需的几乎所有样板代码。

Matt Thompson(我很想念他的作品)写了一篇很有见地的文章 post关于何时应该考虑 CoreData 与 NSKeyedArchiver 等。始终方便保留以供引用。

我将我的解决方案分为两部分,在第一部分中,我回顾了您的原始问题,只是为了给您一些基本的指导。我处理 MagicalRecord 的最后一部分,因为我真的觉得它可能更适合您,因为它的学习曲线更轻松。毕竟我们是来发布应用程序的,随着你深入 iOS 学习 Core Data。

问题回顾

在我深入研究之前,我想探索一些我们可以用您的解决方案纠正的错误,这样您就可以理解为什么它不起作用。

// Core data setup
let context = (UIApplication.sharedApplication().delegate as AppDelegate).managedObjectContext!

我知道 Apple 将上下文放入 AppDelegate 中,但这是一个非常困惑的 hack,我通常发现最好在某个地方有一个 CoreData 单例来包装你的上下文。坚持单一责任原则很好,App Delegate 负责处理 App Events 和实例化 ViewController 层次结构。不用于管理核心数据堆栈。

var newUser : User? = nil
var results = NSArray()

这很快,为什么不 var results:[AnyObject] = []

var hasAccount = Bool()

你是说,var hasAccount = false....

但是让我们快进,您不需要预先定义所有这些变量,任何阅读您的代码的人都必须扫描这么多行才能真正了解您要实现的目标。让我们清理一下:

// Core data fetching
let userRequest = NSFetchRequest(entityName: "User")
userRequest.fetchLimit = 1
if let user = context.executeFetchRequest(request, error: nil)?.first as? User {
//now we have a user
} else {
//no user
}

新手没有意识到的一个大陷阱是 NSManagedObjectContext 保存操作只保存了一层。如果该上下文直接来自持久性存储,那么您的更改将保存到磁盘,但如果不是,则该保存需要递归调用该上下文父级上的保存等。这是文档:

If a context’s parent store is a persistent store coordinator, then changes are committed to the external store. If a context’s parent store is another managed object context, then save: only updates managed objects in that parent store. To commit changes to the external store, you must save changes in the chain of contexts up to and including the context whose parent is the persistent store coordinator.

因此,如果您的上下文有一个 parentContext,那么您的保存操作永远不会将用户保存到磁盘:)

进入魔法记录

开始使用 Magical Record 非常简单:

MagicalRecord.setupCoreDataStackWithAutoMigratingSqliteStoreNamed(MyCoreDataStoreName)

这通常会出现在您的 App Delegate 中。他们在大多数 Core Data 类上也有大量惊人的类别,用于常见的 Core Data 操作,以及一些经过深思熟虑的基础设施,用于处理多线程问题。

所以现在你想在你的数据库中建立一条应该只有一条的记录。在开始之前,您必须确保也只有一个对象负责访问此用户属性,或者至少确保只有一个对象可以创建此用户属性。

为简单起见,我们将此类称为 UserManager。用户管理器将负责管理我们要对用户执行的所有操作。现在它只需要确保当我们访问它时,数据库中总是有一个。

class UserManager {
class var sharedManager : UserManager {
struct Static {
static let instance : UserManager = UserManager()
}
return Static.instance
}

func currentUser() -> CurrentUser {
if let user = CurrentUser.MR_findFirst() as? CurrentUser {
return user
} else {
let user = CurrentUser.MR_createEntity() as CurrentUser
user.managedObjectContext!.MR_saveToPersistentStoreAndWait()
return user
}
}
}

现在我们有了一个单例,它将始终保证我们在数据库中只有一个用户。您还提到您希望能够更新您的用户,可以将一个简单的实现添加到我们的 UserManager 中:

func updateUser(userUpdateHandler: ((user: CurrentUser) -> Void)) {
MagicalRecord.saveWithBlock { (context) -> Void in
let user = self.currentUser()
userUpdateHandler(user: user)
//as the app grows you could probably post a notification
//here so any interested parties could update their info
//if the user changes....
}
}

从你的 View Controller 中调用它是微不足道的:

    //the updateUser function isn't called
//on the main thread so we need to capture
//the values from the UI so we can safely use
//them in the background
let firstName = firstNameTextField.text
let lastName = lastNameTextField.text
let email = emailTextField.text
let password = passwordTextField.text
UserManager.sharedManager.updateUser { (user) -> Void in
user.firstName = firstName
user.lastName = lastName
user.email = email
user.password = password
user.accountType = 0
}

瞧,您现在已经实现了一组非常标准的函数来处理您应用中的用户。

关于ios - Swift CoreData 编辑/更新实体,当它只有 1 个实例时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29289951/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com