【发布时间】:2016-11-30 12:45:47
【问题描述】:
我在 Xcode 8 的核心数据编辑器中找到关于新代码生成功能的文档有点稀疏。
这是一个“在 Objective-C 中,我会……”之类的问题。
我正在尝试声明一个具有 2 种方法的协议:
@property (strong, readonly) NSNumber *serverId;
+ (instancetype)objectWithServerId:(NSNumber*)serverId inContext:(NSManagedObjectContext*)moc;
在 Objective-C 中,我会使用 mogenerator 来声明生成的基类应该是“MyBaseClass”。
在那个基类中,我可以实现一次该类方法。在核心数据编辑器中,我只需要确保我的实体具有该属性。在“人类可读”文件中,我会声明它符合那个协议,并且因为它继承自那个基类(基本上是抽象的),它可以调用上面列出的那个类方法。
我认为使用强类型,这可能是不可能的。我已经让它工作了,但是我创建的每个子类(使用 Xcode 生成的扩展)都必须实现这个方法,而我更愿意将这个方法写一次作为泛型。
在 Swift 中,我将该属性添加到实体(没有父级,因此它是 NSManagedObject 的子类),然后这样做:
protocol RemoteObjectProtocol {
var serverId: Int64 {get}
static func object<T: NSManagedObject>(WithServerId serverId: Int64, context: NSManagedObjectContext!) -> T?
}
import CoreData
@objc(TestObject)
class TestObject: NSManagedObject {
}
extension TestObject: RemoteObjectProtocol {
// by nature of it being in the generated core data model, we just need to declare its conformance.
static func object<T: NSManagedObject>(WithServerId serverId: Int64, context: NSManagedObjectContext!) -> T? {
// IF YOU FIND A BETTER WAY TO SOLVE THIS, PLEASE DO!
// I would have loved to use a baseclass RemoteObject: NSManagedObject, where you can just implement this
// Method. But there was no way for it to play nicely with the CoreData Editor
// in addition, the convenience method generated by Xcode .fetchRequest() only seems to work outside of this extension.
// Extensions can't make use of other extensions
// So we create the fetch request 'by hand'
let fetchRequest = NSFetchRequest<TestObject>(entityName: "TestObject")
fetchRequest.predicate = NSPredicate(format: "serverId == %i", serverId)
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "serverId", ascending: true)]
fetchRequest.fetchLimit = 1
do {
let fetchedObjects = try context.fetch(fetchRequest)
return fetchedObjects.first as! T?
} catch {
log.warning("Failed to fetch object with serverId:\(serverId) error:\(error)")
}
return nil
}
}
【问题讨论】:
标签: ios objective-c swift xcode core-data