我仍然无法理解
Swift中泛型的一些微妙之处.我定义了以下类型:
protocol SomeProtocol { func setValue(value: Int) } class ProtocolLabel : UILabel,SomeProtocol { func setValue(value: Int) { } } class ProtocolImageView : UIImageView,SomeProtocol { func setValue(value: Int) { } }
viewForValue(2)
现在我定义了以下功能.我希望T是一个符合协议SomeProtocol的UIView.
func viewForValue<T where T: SomeProtocol,T: UIView>(param: Int) -> UIView { var someView: T if param > 0 { someView = ProtocolLabel() as T } else { someView = ProtocolImageView() as T } someView.setValue(2) someView.frame = CGRectZero return someView }
viewForValue(2) // <-- Type 'UIView' does not conform to protocol 'SomeProtocol'
似乎在where子句中我不能指定不实现协议的类.这是为什么?
提前致谢.
解决方法
viewForValue应该返回一个继承自UIView并实现SomeProtocol的类.
您已经定义了两个没有直接关系的类 – 它们只是从UIView继承并实现SomeProtocol.
您已经定义了两个没有直接关系的类 – 它们只是从UIView继承并实现SomeProtocol.
当函数必须确定返回类型时,两个类继承的直接具体类型是UIView,这就是viewForValue返回的内容.
为了解决这个问题,你必须通过创建一个继承自UIView并实现SomeProtocol的第三类来创建两个类之间的直接和具体的关系:
protocol SomeProtocol { func setValue(value: Int) } class SomeClass: UIView,SomeProtocol { func setValue(value: Int) { } } class SomeSubclass : SomeClass { } class SomeOtherSubclass : SomeClass { } func viewForValue<T where T: SomeProtocol,T: SomeClass>(param: Int) -> T { var someView: T if param > 0 { someView = SomeSubclass() as T } else { someView = SomeOtherSubclass() as T } someView.setValue(2) someView.frame = CGRectZero return someView } viewForValue(2)
附录:阅读下面的OP评论,目的是动态实例化从UIView继承的现有UIKit类.因此,建议的解决方案不适用.
我认为通过实现SomeProtocol来扩展UIView应该可行:
protocol SomeProtocol { func setValue(value: Int) } extension UIView : SomeProtocol { func setValue(value: Int) { } } func viewForValue<T where T: SomeProtocol,T: UIView>(param: Int) -> UIView { var someView: T if param > 0 { someView = UILabel() as T } else { someView = UIImageView() as T } someView.setValue(2) someView.frame = CGRectZero return someView }
但看起来有一个编译器错误.操场上的此代码显示一条消息,指出:
Communication with the playground service was interrupted unexpectedly.
The playground service “com.apple.dt.Xcode.Playground” may have generated a crash log.
而在iOS应用程序中,由于分段错误,编译失败11.