self
разрешается во время выполнения.T
разрешается во время компиляции.Таким образом, во время компиляции ваш код ведет себя так:
let returnValue: UIView? = WidgetAddHeaderView.loadFromNib()
return returnValue
loadFromNib
является универсальным для своего возвращаемого типа.Учитывая этот код, единственный допустимый тип возврата - UIView
.Опять же, это решено во время компиляции .
self
, с другой стороны, это просто переменная.Это очень специфическая переменная, но на самом деле это просто переменная.Имеет значение во время выполнения.Так что type(of: self)
оценивается во время выполнения.А динамическая диспетчеризация обрабатывается во время выполнения.
Ошибка в том, что вы на самом деле не хотите возвращать «некоторый неизвестный T, который соответствует UIViewNibLoading» (то, что вы говорите, вы возвращаете, делая тип возвратародовое).То, что вы хотите вернуть, это Self
, класс, членом которого является статическая функция (определяется во время компиляции).Итак, вы говорите так:
extension UIViewNibLoading where Self : UIView {
static func loadFromNib() -> Self {
print(nibName)
return UINib(nibName: nibName, bundle: nil)
.instantiate(withOwner: nil, options: nil)[0] as! Self
}
}
Или вы могли бы обещать меньше (поскольку вашему звонящему на самом деле все равно) и сделать это:
extension UIViewNibLoading where Self : UIView {
static func loadFromNib() -> UIView {
print(nibName)
return UINib(nibName: nibName, bundle: nil)
.instantiate(withOwner: nil, options: nil)[0]
}
}
Но нет никаких причин делать этот методуниверсальный, и это на самом деле больно, как вы видели.