我试着为UIView编写一个静态方法,它从nib实例化该类的视图。方法应该是通用的,并在每个UIView
子类上工作。此外,我想保存类型的信息 - 这样,例如,在这段代码自我,协议扩展和非最终类
let myView = MyView.loadFromNib()
编译器将指示myView
有MyView
类。经过几次试验后,我决定使用协议扩展,否则我将无法访问方法体内的Self
。
看起来这应该工作:
protocol NibLoadable {
static func loadFromNib(name: String?) -> Self
}
extension NibLoadable where Self: UIView {
static func loadFromNib(name: String? = nil) -> Self {
let nibName = name ?? "\(self)"
let nib = UINib(nibName: nibName, bundle: nil)
return nib.instantiateWithOwner(nil, options: nil)[0] as! Self
}
}
extension UIView: NibLoadable {}
但事实并非如此。我得到编译错误
Method 'loadFromNib' in non-final class 'UIView' must return `Self` to conform to protocol 'NibLoadable'
而且发生了两件奇怪的事情。首先,如果我将协议声明更改为
protocol NibLoadable {
static func loadFromNib(name: String?) -> UIView
}
一切正常,包括类型推断。第二,我可以进一步删除where
子句:
extension NibLoadable {
...
}
它继续工作!
所以任何人都可以解释一下为什么我的第一个变体失败了,为什么第二个和第三个工作正常以及它如何与最终类相关?
我不知道确切的答案你的问题,但为什么不只是延长'UIView'直接跳过协议? – JAL
现在没有时间来测试它,但我不认为返回自我是一个很好的模式。你应该使用协议的关联类型: https://www.natashatherobot.com/swift-protocols-with-associated-types/ – 66o
@JAL:在我开始使用协议之前,我尝试了这种方法。它不适合我,因为在这种情况下,我不能在方法体内使用'Self'。没有'Self'我就无法得到这种类型推断。 –