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'
Help?
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)
}
}
(Updated for Swift 3/4 now. Solutions for earlier Swift versions can be found in the edit history.)
You can use unsafeDowncast
to cast the return value
of NSEntityDescription.insertNewObject()
to Self
(which is the type on which the method is actually called):
extension NSManagedObject {
class func create(in context: NSManagedObjectContext) -> Self {
let classname = entityName()
let object = NSEntityDescription.insertNewObject(forEntityName: classname, into: context)
return unsafeDowncast(object, to: self)
}
// Returns the unqualified class name, i.e. the last component.
// Can be overridden in a subclass.
class func entityName() -> String {
return String(describing: self)
}
}
Then
let obj = YourEntity.createInContext(context)
works and the compiler infers the type of obj
correctly as YourEntity
.