当创建NSManagedObject的扩展帮助程序来创建一个新的托管对象子类时,swift提供了自我类型来模拟这个很棒的instancetype,但是我似乎不能从AnyObject打字.以下代码不会编译错误’AnyObject’不能转换为’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) } }
诀窍是使用一个通用的助手方法来推断自己的类型
从上下文.您的className()方法也可以稍微简化,并且可以通过entityName()更好的名称:
从上下文.您的className()方法也可以稍微简化,并且可以通过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.
更新:使用How to use generic types to get object with same 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而不是帮助方法,如注释中所建议的:
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 } }