什么是快速相当于NSObject <protocol>?

时间:2015-08-11 17:51:00

标签: swift protocols nsobject

我有一个类,需要使用NSObject子类的变量进行设置,并实现某个协议。

protocol ProtoTest {
    var foo: Int { get set }
}


class AClass: NSObject,  ProtoTest {
    var foo: Int = 3
}


class BClass: NSObject,  ProtoTest {
    var foo: Int = 4
}

class Consumer {

    var protoInstance: ProtoTest?  //Does not cary any information of the class just the protocol
    var protoInstance2: protocol<NSObjectProtocol, ProtoTest>?

    init(x: ProtoTest) {
        self.protoInstance = x
        self.protoInstance2 = nil
    }

    init(x: protocol<NSObjectProtocol, ProtoTest>) {
        self.protoInstance2 = x
        self.protoInstance = nil
    }

    func doSomething() {
        if let x = protoInstance {
            x.copy() //'ProtoTest' does not have a member named 'copy'
        }
        if let x = protoInstance2 {
            x.copy()    //protocol<NSObjectProtocol, ProtoTest> does not have a member named 'copy'

        }
    }
}

在上面的例子中,变量的声明都不起作用。既然他们都不知道基类?

如何在swift中实现此功能?

2 个答案:

答案 0 :(得分:2)

Swift中通常的等同于NSObject<Protocol>只是Protocol。通常,此协议被声明为类协议,以保证它将被类采用。

如果您还需要NSObject协议方法(例如respondsToSelector:),则make Protocol采用NSObjectProtocol。

如果问题仅仅是您想要调用copy()并且您无法说服编译器让您这样做,那么也可以采用NSCopying(或者只使用respondsToSelector:和{ {1}}完全绕过编译器。)

答案 1 :(得分:1)

你可以通过几种方式做到这一点。首先,您可以Consumer通用:

class Consumer<T: NSObject where T: Prototest> {
    var protoInstance: T?
    var protoInstance2: T?
}

如果您这样做,那么对protoInstanceprotoInstance2的所有引用都将从NSObject继承,您将能够直接在对象上调用.copy()等方法

如果您不希望Consumer是通用的,则可以使用通用参数强制限制init方法,如下所示:

class Consumer {
    // ...
    init<T: NSObject where T: Prototest>(x: T) {
        protoInstance = x
    }
}

如果你这样做,我们保证protoInstance将成为NSObject,但你必须强制转换为NSObject才能使用NSObject中的任何一个方法:

func doSomething() {
    if let x = protoInstance as? NSObject {
        x.copy()
    }
}

编辑:

请注意,我不确定您是否真的希望protoInstanceprotoInstance2属于不同的类型我对您的问题有点不清楚。如果您确实希望它们是不同的类型,我可以为此答案添加其他建议。