Der Trick ist, eine generische Hilfsmethode zu verwenden, die die Art der self
aus dem Kontext folgert. Ihre className()
Verfahren kann auch leicht vereinfacht werden und ein besserer Name könnte von 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
}
}
Dann
let obj = YourEntity.createInContext(context)
Werke und der Compiler folgert die Art der obj
korrekt als YourEntity
.
Update:
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
}
}
: Mit den Ideen von
How to use generic types to get object with same type kann dies auch mit einer globalen wiederverwendbaren Funktion anstelle des Hilfsmethode zu werfen den Rückgabewert in dem entsprechenden Typen durchgeführt werden
Update für Swift 1.2/Xcode 6.3 und 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
}
}
Oder mit unsafeBitCast
anstelle einer Hilfsmethode, wie sie in den Kommentaren vorgeschlagen:
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
}
}
2 ¢: Diese generische Funktion ist ein ziemlich gutes Anwendungsbeispiel für das Schlüsselwort 'private'. – Mazyod
@Mazyod: Guter Vorschlag, fertig. –
In Swift 2 ist Split keine globale Funktion mehr. Wir können stattdessen classString.componentsSeparatedByString (".") Verwenden. –