如何在NSManagedObject Swift扩展中创建托管对象子类的实例? [英] How can I create instances of managed object subclasses in a NSManagedObject Swift extension?
问题描述
在创建 NSManagedObject
的扩展帮助以创建新的托管对象子类时,swift提供 Self
类型mimic instancetype
这是伟大的,但我似乎不能类型从 AnyObject
。以下代码不会编译时出错AnyObject不能转换为自我
When creating an extension helper to NSManagedObject
to create a new managed object subclass, swift provides the Self
type to mimic instancetype
which is great, but i can't seem to typecast from AnyObject
. The below code does not compile with error 'AnyObject' is not convertible to 'Self'
帮助?
extension NSManagedObject
{
class func createInContext(context:NSManagedObjectContext) -> Self {
var classname = className()
var object: AnyObject = NSEntityDescription.insertNewObjectForEntityForName(classname, inManagedObjectContext: context)
return object
}
class func className() -> String {
let classString = NSStringFromClass(self)
//Remove Swift module name
let range = classString.rangeOfString(".", options: NSStringCompareOptions.CaseInsensitiveSearch, range: Range<String.Index>(start:classString.startIndex, end: classString.endIndex), locale: nil)
return classString.substringFromIndex(range!.endIndex)
}
}
推荐答案
诀窍是使用一个泛型助手方法, self
。您的 className()
方法也可以稍微简化,更好的名称可以通过 entityName()
:
The trick is to use a generic helper method which infers the type of self
from the context. Your className()
method can also be simplified slightly, and a better name might by entityName()
:
extension NSManagedObject
{
class func createInContext(context:NSManagedObjectContext) -> Self {
return createInContextHelper(context)
}
private class func createInContextHelper<T>(context:NSManagedObjectContext) -> T {
let classname = entityName()
let object = NSEntityDescription.insertNewObjectForEntityForName(classname, inManagedObjectContext: context) as! T
return object
}
class func entityName() -> String {
let classString = NSStringFromClass(self)
// The entity is the last component of dot-separated class name:
let components = split(classString, { $0 == "." })
return components.last ?? classString
}
}
然后
let obj = YourEntity.createInContext(context)
工程,编译器将 obj
的类型正确推荐为 YourEntity
。
works and the compiler infers the type of obj
correctly as YourEntity
.
更新:使用如何使用泛型类型获取相同类型的对象,这也可以使用全局可重用函数而不是helper方法将返回值转换为适当的类型:
Update: Using the ideas from How to use generic types to get object with same type, this can also be done with a global reusable function instead of the helper method to cast the return value to the appropriate type:
func objcast<T>(obj: AnyObject) -> T {
return obj as T
}
extension NSManagedObject
{
class func createInContext(context:NSManagedObjectContext) -> Self {
let classname = entityName()
let object: AnyObject = NSEntityDescription.insertNewObjectForEntityForName(classname, inManagedObjectContext: context)
return objcast(object)
}
class func entityName() -> String {
let classString = NSStringFromClass(self)
// The entity is the last component of dot-separated class name:
let components = split(classString, { $0 == "." })
return components.last ?? classString
}
}
更新 Swift 1.2 / Xcode 6.3 和 Swift 2 / Xcode 7:
func objcast<T>(obj: AnyObject) -> T {
return obj as! T
}
extension NSManagedObject
{
class func createInContext(context:NSManagedObjectContext) -> Self {
let classname = entityName()
let object: AnyObject = NSEntityDescription.insertNewObjectForEntityForName(classname, inManagedObjectContext: context)
return objcast(object)
}
class func entityName() -> String {
let classString = NSStringFromClass(self)
// The entity is the last component of dot-separated class name:
let components = classString.componentsSeparatedByString(".")
return components.last ?? classString
}
}
或 unsafeBitCast
而不是注释中建议的辅助方法:
Or with unsafeBitCast
instead of a helper method, as suggested in the comments:
extension NSManagedObject
{
class func createInContext(context:NSManagedObjectContext) -> Self {
let classname = entityName()
let object: AnyObject = NSEntityDescription.insertNewObjectForEntityForName(classname, inManagedObjectContext: context)
return unsafeBitCast(object, self)
}
class func entityName() -> String {
let classString = NSStringFromClass(self)
// The entity is the last component of dot-separated class name:
let components = classString.componentsSeparatedByString(".")
return components.last ?? classString
}
}
这篇关于如何在NSManagedObject Swift扩展中创建托管对象子类的实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!