- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
这个问题似乎已经被问了很多了。但我一直无法找到快速的解决方案。
我有一个名为“用户”的实体,应该只有一个。所以在它第一次被创建之后。我需要编辑/更新它的值而不是创建更多值。
我确实在 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/
IO 设备如何知道属于它的内存中的值在memory mapped IO 中发生了变化? ? 例如,假设内存地址 0 专用于保存 VGA 设备的背景颜色。当我们更改 memory[0] 中的值时,VGA
我目前正在开发一个使用Facebook sdk登录(通过FBLoginView)的iOS应用。 一切正常,除了那些拥有较旧版本的facebook的人。 当他们按下“使用Facebook登录”按钮时,他
假设我有: this - is an - example - with some - dashesNSRange将使用`rangeOfString:@“-”拾取“-”的第一个实例,但是如果我只想要最后
Card.io SDK提供以下详细信息: 卡号,有效期,月份,年份,CVV和邮政编码。 如何从此SDK获取国家名称。 - (void)userDidProvideCreditCardInfo:(Car
iOS 应用程序如何从网络服务下载图片并在安装过程中将它们安装到用户的 iOS 设备上?可能吗? 最佳答案 您无法控制应用在用户设备上的安装,因此无法在安装过程中下载其他数据。 只需在安装后首次启动应
我曾经开发过一款企业版 iOS 产品,我们公司曾将其出售给大型企业,供他们的员工使用。 该应用程序通过 AppStore 提供,企业用户获得了公司特定的配置文件(包含应用程序配置文件)以启用他们有权使
我正在尝试将 Card.io SDK 集成到我的 iOS 应用程序中。我想为 CardIO ui 做一个简单的本地化,如更改取消按钮标题或“在此保留信用卡”提示文本。 我在 github 上找到了这个
我正在使用 CardIOView 和 CardIOViewDelegate 类,没有可以设置为 YES 的 BOOL 来扫描 collectCardholderName。我可以看到它在 CardIOP
我有一个集成了通话工具包的 voip 应用程序。每次我从我的 voip 应用程序调用时,都会在 native 电话应用程序中创建一个新的最近通话记录。我在 voip 应用程序中也有自定义联系人(电话应
iOS 应用程序如何知道应用程序打开时屏幕上是否已经有键盘?应用程序运行后,它可以接收键盘显示/隐藏通知。但是,如果应用程序在分屏模式下作为辅助应用程序打开,而主应用程序已经显示键盘,则辅助应用程序不
我在模拟器中收到以下错误: ImageIO: CGImageReadSessionGetCachedImageBlockData *** CGImageReadSessionGetCachedIm
如 Apple 文档所示,可以通过 EAAccessory Framework 与经过认证的配件(由 Apple 认证)进行通信。但是我有点困惑,因为一些帖子告诉我它也可以通过 CoreBluetoo
尽管现在的调试器已经很不错了,但有时找出应用程序中正在发生的事情的最好方法仍然是古老的 NSLog。当您连接到计算机时,这样做很容易; Xcode 会帮助弹出日志查看器面板,然后就可以了。当您不在办公
在我的 iOS 应用程序中,我定义了一些兴趣点。其中一些有一个 Kontakt.io 信标的名称,它绑定(bind)到一个特定的 PoI(我的意思是通常贴在信标标签上的名称)。现在我想在附近发现信标,
我正在为警报提示创建一个 trigger.io 插件。尝试从警报提示返回数据。这是我的代码: // Prompt + (void)show_prompt:(ForgeTask*)task{
您好,我是 Apple iOS 的新手。我阅读并搜索了很多关于推送通知的文章,但我没有发现任何关于 APNS 从 io4 到 ios 6 的新更新的信息。任何人都可以向我提供 APNS 如何在 ios
UITabBar 的高度似乎在 iOS 7 和 8/9/10/11 之间发生了变化。我发布这个问题是为了让其他人轻松找到答案。 那么:在 iPhone 和 iPad 上的 iOS 8/9/10/11
我想我可以针对不同的 iOS 版本使用不同的 Storyboard。 由于 UI 的差异,我将创建下一个 Storyboard: Main_iPhone.storyboard Main_iPad.st
我正在写一些东西,我将使用设备的 iTunes 库中的一部分音轨来覆盖 2 个视频的组合,例如: AVMutableComposition* mixComposition = [[AVMutableC
我创建了一个简单的 iOS 程序,可以顺利编译并在 iPad 模拟器上运行良好。当我告诉 XCode 4 使用我连接的 iPad 设备时,无法编译相同的程序。问题似乎是当我尝试使用附加的 iPad 时
我是一名优秀的程序员,十分优秀!