Swift 2.0:返回Self

时间:2015-11-19 11:41:57

标签: swift swift2 protocol-extension

为了扩展我的NSManagedObject子类的一些功能,我定义了一系列协议:

protocol ManagedObjectFindable {
    static func find(format:String, arguments: [AnyObject]?, inContext context:NSManagedObjectContext, entityName:String?) -> Self?
}

protocol UniquelyIdentifiable: ManagedObjectFindable {

    var identifier: NSNumber? { get }
    static func findWithIdentifier(identifier: Int, inContext context:NSManagedObjectContext) -> Self?
}

那么在其数据模型实体中具有标识符的每个NSManagedObject都可以符合UniquelyIdentifiable

为此目的,我正在使用Swift 2.0 Protocol Extensions,其中:

extension UniquelyIdentifiable {

    static func findWithIdentifier(identifier: Int, inContext context:NSManagedObjectContext) -> Self? {
        return self.find("identifier == %lld", arguments: [NSNumber(longLong: Int64(identifier))], inContext: context, entityName:nil)
    }
}

其中find定义为:

extension NSManagedObject: ManagedObjectFindable {
    /** returns single entity if found, nil otherwise */
    class func find(format:String, arguments: [AnyObject]?, inContext context:NSManagedObjectContext, entityName:String? = nil) -> Self? {

        let objectEntityName:String
        if let name = entityName {
            objectEntityName = name
        } else {
            objectEntityName = String(self)
        }

        let fetchRequest = NSFetchRequest()
        fetchRequest.entity = NSEntityDescription.entityForName(objectEntityName, inManagedObjectContext: context)
        fetchRequest.fetchLimit = 1
        fetchRequest.predicate = NSPredicate(format: format, argumentArray: arguments)

        var persistentEntityº:NSManagedObject?
        context.performBlockAndWait {

            do {
                let fetchResults = try context.executeFetchRequest(fetchRequest)
                if (fetchResults.count != 0){
                    persistentEntityº = fetchResults.first as? NSManagedObject
                }
            } catch {}
        }

        if let persistentEntity = persistentEntityº {
            return _safeObjectSelfCast(persistentEntity)
        } else {
            return nil
        }
    }
}
func _unsafeObjectSelfCast<T>(obj: AnyObject!) -> T { return obj as! T }
func _safeObjectSelfCast<T>(obj: AnyObject) -> T?   { return obj as? T }

现在这些方法正确地返回Self?并且编译器对编码时间保持沉默,但是在编译它时会给出错误Method 'findWithIdentifier(_:inContext:)' in non-final class must return 'Self' to conform to protocol 'UniquelyIdentifiable'

现在的问题是,如果不是在协议扩展中实现该方法,我只是扩展我的NSManagedObject子类,它会很好,但是当你完全复制时,它会破坏协议扩展的目的。几十个NSManagedObject子类中的相同代码。

任何解决方法,或者我真的错过了什么?

1 个答案:

答案 0 :(得分:2)

简答:Self?的扩展名更改为NSManagedObject?

长答案:协议要求中的 Self充当将实现该协议的类的占位符。所以,如果你有

protocol SomeProtocol {
   func returnSomething() -> Self
}

这意味着,如果您在Int上实施,则功能returnSomething()应返回Int,如果您在Double上实施,则应返回Double

由于您要在UniquelyIdentifiable上实施NSManagedObject并且您的协议有Self?要求,因此您应该返回NSManagedObject?