当使用 NSCoding
初始化我的类的实例时,我想用 Core Data 数据库中的现有对象替换它,而不是调用:
super.init(entity: ..., insertIntoManagedObjectContext: ...)
因为这会将一个新对象插入到数据库中。
class MyClass: NSManagedObject, NSCoding {
required init(coder aDecoder: NSCoder) {
// Find a preexisting object in the Core Data database
var ctx = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext!
var fs = NSFetchRequest(entityName: "MyClass")
// ... Configure the fetch request based on values in the decoder
var err: NSErrorPointer = nil
var results = ctx.executeFetchRequest(fs, error: err)
// ... Error handling, etc
newObject = results[0] as! MyClass
// Attempt to replace self with the new object
self = newObject // ERROR: "Cannot assign to 'self' in a method"
}
func encodeWithCoder(aCoder: NSCoder) {
// Encode some identifying property for this object
}
}
这是一个 fairly common Objective-C 模式,但我不知道如何在 Swift 1.2 中复制它,因为将另一个对象分配给 self
会产生编译错误:
Cannot assign to 'self' in a method
即使成功了,Swift 似乎也要求我调用 NSManagedObject
的指定初始化程序,它将新对象插入到数据库中。
如何在初始化时用数据库中预先存在的对象替换对象?如果它不可能(如果是这种情况请提供引用),我应该改用什么模式?
最佳答案
您可以使用 awakeAfterUsingCoder(_:)
用于替换 self
:
You can use this method to eliminate redundant objects created by the coder. For example, if after decoding an object you discover that an equivalent object already exists, you can return the existing object. If a replacement is returned, your overriding method is responsible for releasing the receiver.
class Item: NSManagedObject, NSCoding {
@NSManaged var uuid: String
@NSManaged var name: String?
override init(entity: NSEntityDescription, insertIntoManagedObjectContext context: NSManagedObjectContext?) {
super.init(entity: entity, insertIntoManagedObjectContext: context)
}
required init(coder aDecoder: NSCoder) {
let ctx = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext!
let entity = NSEntityDescription.entityForName("Item", inManagedObjectContext: ctx)!
// Note: pass `nil` to `insertIntoManagedObjectContext`
super.init(entity: entity, insertIntoManagedObjectContext: nil)
self.uuid = aDecoder.decodeObjectForKey("uuid") as! String
}
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(self.uuid, forKey: "uuid")
}
override func awakeAfterUsingCoder(aDecoder: NSCoder) -> AnyObject? {
let ctx = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext!
let fetch = NSFetchRequest(entityName: "Item")
fetch.predicate = NSPredicate(format: "uuid == %@", self.uuid)
if let obj = ctx.executeFetchRequest(fetch, error: nil)?.first as? Item {
// OK, the object is still in the storage.
return obj
}
else {
// The object has already been deleted. so insert and use `self`.
ctx.insertObject(self)
return self
}
}
}
关于ios - 如何在 Swift 中的 NSCoding 初始化时返回预先存在的核心数据对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31372584/