1

我编写了一些我认为应该在 Swift 2 (Xcode 7b4) 中工作的代码,但它没有编译。我希望对我正在尝试做的事情是否有效有一些想法。

考虑这个示例Array扩展:

extension Array where Element: AnyObject {
    mutating func appendUniqueInstance(e: Element) {
        for element in self {
            if (element === e) {
                return
            }
        }

        self.append(e)
    }
}

首先,元素为 的数组是什么意思AnyObject?基本上我是说数组应该包含一组异构的非值类型对象,可以比较例如相等(===)。

示例函数appendUniqueInstance()仅将元素插入到数组中(如果它不在数组中)。这类似于Set insert()操作,但显然提供了排序并且(更重要的是)不强加Set' 的同质类型要求(通过Equatable' 的使用Self)。

如果我现在定义一个协议P和一个C实现的类P

protocol P : AnyObject {}

class C : P {}

并实例化一个C

let c = C()

那么这些非常明显的事情是真的:

let cIsAnyObject = c as AnyObject   // ok
let cIsP = c as P                   // ok

我现在可以执行以下操作:

var a1 = [AnyObject]()              // []

a1.appendUniqueInstance(c)          // [c]
a1.appendUniqueInstance(c)          // [c]

到目前为止,一切都很好,但现在对于问题案例:

var a2 = [P]()

a2.append(c)                        // ok, -> [c]

// Compiler error: Cannot invoke 'appendUniqueInstance' with an argument list of type '(C)'
a2.appendUniqueInstance(c)

在这里,a2被键入为 的数组,因此对的实例P执行此操作应该是完全有效的,并且确实该行按我们预期的那样工作。appendPa2.append(c)

然而,调用Array扩展函数会appendUniqueInstance()产生编译器错误。

据我所知,编译器似乎对可以传递的内容感到困惑,appendUniqueInstance()而没有意识到(或由于某种原因允许)C(via P) 是一个AnyObject.

顺便说一句,如果我P改为声明:

@objc protocol P : AnyObject {}

然后一切都编译得很好,但我还必须确保协议中的所有内容都P符合@objc,这不是我想要的。

所以,在这一切之后,我的问题是:这看起来应该可行吗?我希望这不仅仅是一些声明语法错误的情况,但我想如果是这样我会很高兴。

4

2 回答 2

0

如果你点击命令,AnyObject 你会注意到它是一个符合@objc 的协议。所以我猜这就是它要求使用@objc 的原因。我注意到如果我们使 C 成为 NSObject 的子类,您不需要显式地实现方法 fromP以符合 @objc

@objc protocol P : AnyObject {
    func hey()
}

class C : NSObject, P {
    func hey() {
        print("hey")
    }
}
于 2016-02-09T15:39:52.090 回答
0

看来编译器在我写原始问题时报告的错误只是误导,我试图获得的功能不(现在仍然不)被 Swift 支持。

使用 Xcode 8.2.1 和 Swift 3 会报告更准确的错误:

// error: using 'P' as a concrete type conforming
//   to protocol 'AnyObject' is not supported
a2.appendUniqueInstance(c)
于 2017-02-26T17:44:06.223 回答