NSObject<Protocol> 的 swift 等价物是什么?

whats the swift equivalent of NSObject<Protocol>?

我有一个 class 需要设置一个 NSObject 子变量 class 并且它实现了某个协议。

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'

        }
    }
}

在上面的例子中,变量的声明都不起作用。因为他们都不知道基数 class?

如何在 swift 中实现它?

您可以通过多种方式完成此操作。首先,您可以使 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 是不同的类型 我对您的问题有点不清楚。如果您确实希望它们是不同的类型,我可以在此答案中添加其他建议。

通常 相当于 Swift 中的 NSObject<Protocol> 就是 Protocol。通常,此协议声明为 class 协议 以保证它将被 class.

采用

如果你还需要NSObject的协议方法(比如respondsToSelector:,那就让Protocol采用NSObjectProtocol。

如果问题仅仅是你想调用 copy() 而你不能说服编译器让你这样做,那么也采用 NSCopying(或者只使用 respondsToSelector:performSelector: 完全绕过编译器)。