Я попытался написать статический метод для 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 {
...
}
И он продолжает работать!
Так может ли кто-нибудь объяснить мне, почему мой первый вариант не удается, почему вторая и третья работают нормально и как это связано с окончательными классами?