如何将协议转换为NSObject <protocol>以访问受约束的扩展接口?

时间:2017-01-09 07:55:47

标签: generics swift3 swift-extensions

问题涉及 Swift3 。 从版本4开始,您最终可以将对象强制转换为gvar

Type<Protocol>

我有一个协议和从中继承的多种类型。

someObject as (Type & Protocol)

对于该协议,我有一个对象继承自NSObject的情况:

扩展名是:

A, B, C, D: CKEntity (pseudocode)

多个案例的工作。

我有一个函数,它接受实现CKEntity的Class(Type)。

如果它也是NSObject,我需要检查它是否符合案例。 如果是,请调用相应的函数。

我想要完成的原型:

extension CKEntity where Self : NSObject {

static func method() {
    ...
}

不能工作。

问题是:

如何将类型(Protocol.Type)转换为NSObject.Type(不是实例)以满足扩展约束?

情景(概述):

  1. A的扩展名,其中A是B

  2. A可以是B

  3. 需要将A投射到A:B并到达受约束的A&amp; B界面。

1 个答案:

答案 0 :(得分:0)

找到了解决方案,有点像。

当涉及到扩展 NSObject 时,最好是采用扩展 NSObjectProtocol 而不是NSObject本身(即使你&#39;重新扩展后者)。

原因是NSObject本身不是协议,这给Swift复合协议检查带来了困难。另一方面, NSObjectProtocol 自然地由任何NSObject派生的对象继承,并且是一个协议,这是一个关键。

因此,如果可能的话,我们应该重构将内容向下转换为多个协议的地方(如果可能的话,这可能是关于NSObject的)。

扩展修改如下:

extension NSObjectProtocol where Self : CKEntity {
     static func method() {
         // ...
     }
}

支票是:

 if let extendedType = type as? NSObjectProtocol & CKEntity.Type {
     extendedType.self.method()
 }

它有效!

可以偶然发现的缺点是NSObjectProtocol不包含KVC方法,因此您需要像这样投射对象以获得KVC接口:

extension NSObjectProtocol where Self : CKEntity {

    static var staticVar : String {
        return (Self.self as! NSObject.Type).className()
    }


    var publicVar : String! {
        return (self as! NSObject).value(forKey: "Key") as! String
    }
}