我有一个简单的Result
对象,它应该包含一个对象(类,结构或枚举)和一个Bool
来说明它是否被取消。我需要沿着它的路径询问这个对象(在它到达目的地之前,目的地知道期望什么样的对象)来确定它是否被取消(当时没有担心伴随的对象)。我的对象看起来像:
import Foundation
@objc protocol Resultable {
var didCancel: Bool { get }
}
class Result<T>: Resultable {
let didCancel: Bool
let object: T?
init(didCancel: Bool, object: T?) {
self.didCancel = didCancel
self.object = object
}
}
我的Result
对象可以包装didCancel
标志和实际对象(可以是任何类型),以及它实现Resultable
协议的意思我可以在任何时候询问它,看看是否通过将其转换为Resultable
来取消它。
我理解(虽然不喜欢它)协议必须以@objc
为前缀,以便我们可以投射到它(根据Apple文档)。不幸的是,当我运行下面的代码(在游乐场或项目中)时,我收到一条令人讨厌的"does not implement methodSignatureForSelector:"
错误消息:
let test = Result(didCancel: false, object: NSArray())
println(test.didCancel)
// transform the object into the form it will be received in
let anyTest: AnyObject = test
if let castTest = anyTest as? Resultable {
println(castTest.didCancel)
}
似乎尽管协议以@objc
为前缀,但它也希望实际的类继承自NSObject
(这不是Apple明确要求的要求)。对于泛型类来说,这显然是一个问题。
这里有什么我想念的吗?有什么办法让这个工作?如果做不到的话,是否有任何变通方法(尽管我坚信这种事情应该是可能的 - 也许我们可以希望Apple在某个阶段会废除@objc
协议转换要求)?
更新 看起来这是用Swift 1.2解决的 您现在可以转换为非ObjC协议,并且该对象不必从NSObject继承。
答案 0 :(得分:3)
似乎尽管协议以
@objc
为前缀,但它也希望实际的类继承自NSObject
事实并非如此。例如,以下代码按预期工作:
@objc protocol MyProtocol {
var flag: Bool { get }
}
class MyClass: MyProtocol {
let flag = true
}
let foo:AnyObject = MyClass()
if let p = foo as? MyProtocol {
println(p.flag)
}
问题是:在Swift Generic类中声明的任何方法/属性在Objective-C中是不可见的。因此,从@objc protocol Resultable
的角度来看,didCancel
中声明的Result<T>
属性是不可见的。这就是调用methodSignatureForSelector:
的原因。
此处的解决方法非常烦人:您必须拥有实现Result
的{{1}}的非通用基类。
didCancel