I tried write a static method for UIView which instantiates view of that class from the nib. Method should be generic and work on every UIView subclasses. Also I want to save the type information – so, for example, in this code
let myView = MyView.loadFromNib()
compiler infers that myView has MyView class. After few trials I decided to use protocol extensions, because otherwise I wouldn't have access to Self inside method body.
Looks like this should work:
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 {}
But it doesn't. I get compilation error
Method 'loadFromNib' in non-final class 'UIView' must return `Self` to conform to protocol 'NibLoadable'
And two strange things happen. First, if I change protocol declaration to
protocol NibLoadable {
static func loadFromNib(name: String?) -> UIView
}
Everything works just great, including type inference. And second, I can go further and remove where clause altogether:
extension NibLoadable {
...
}
And it keeps working!
So could anyone please explain me why my first variant fails, why second and third work fine and how it's related to final classes?
UIViewdirectly and skip the protocol? - JALSelfinside of method body. And withoutSelfI couldn't get that type inference. - Alexander Doloz