我有一个奇怪的问题,演员阵容无法正常工作,但控制台显示它是正确的类型.
我有一个公共协议
public protocol MyProtocol { }
我在一个模块中实现它,使用返回实例的公共方法.
internal struct MyStruct: MyProtocol { } public func make() -> MyProtocol { return MyStruct() }
然后,在我的视图控制器中,我触发一个带有该对象的segue作为发送者
let myStruct = make() self.performSegue(withIdentifier: "Bob",sender: myStruct)
到目前为止都很好.
问题出在我的prepare(for:sender :)方法中.
override func prepare(for segue: UIStoryboardSegue,sender: Any?) { if segue.identifier == "Bob" { if let instance = sender as? MyProtocol { print("Yay") } } }
但是,实例转换为MyProtocol始终返回nil.
当我运行po发送者时!在控制台中的MyProtocol,它给出了错误无法将’_SwiftValue'(0x1107c4c70)类型的值转换为’MyProtocol'(0x1107c51c8).但是,po发送器将输出有效的Module.MyStruct实例.
为什么这个演员不起作用?
解决方法
根据Joe Groff在bug report you filed的评论中的说法:
This is an instance of the general “runtime dynamic casting doesn’t bridge if necessary to bridge to a protocol” bug. Since sender is seen as
_SwiftValue
object type,and we’re trying to get to a protocol it doesn’t conform to,we give up without also trying the bridged type.
一个更小的例子是:
protocol P {} struct S : P {} let s = S() let val : Any = s as AnyObject // bridge to Obj-C as a _SwiftValue. print(val as? P) // nil
奇怪的是,首先转换为AnyObject然后转换为协议似乎工作:
print(val as AnyObject as! P) // S()
所以看起来静态输入它作为AnyObject使得Swift也检查了桥接类型的协议一致性,允许强制转换成功.正如Joe Groff在另一篇评论中所解释的那样,其原因是:
The runtime has had a number of bugs where it only attempts certain conversions to one level of depth,but not after performing other conversions (so AnyObject -> bridge -> Protocol might work,but Any -> AnyObject -> bridge -> Protocol doesn’t). It ought to work,at any rate.