I know the rule about convenient init but I was wondering about the general super call outside the class scope on statically proved class instances. But I guess this is not possible because we can't write UIView().super to get the super class (UIResponder) but we can do .self pretty much everywhere.
For other functions it does allow super call (and will correctly invoke the super implementation), but init is a little special since it doesn't really follow the flow of normal function; for one, it won't allow you to leave until every class member is initialised.
In fact compiler won't even let you use super.init anywhere else but inside designated initialiser.
Sorry, my mind switched back to Class Extension, not Protocol Extension.
Since Swift doesn't allow for protocol to require base class yet, I don't think super will work there.
A small side note, you don't really initialize anything in your commonInit method anymore, it's just a common setup, but everything else at that point of time has already been initialized.
Well in Swift 4.2 or maybe in 4.1 this feature slipped by as protocol Foo where Self : MyClass and has been kept but also generalized in Swift 5 to protocol Foo : MyClass. That's why I'm wondering if we should be able to make super calls in an extension where it's proved by the compiler that we're inside a class.
isn't this requiring that the protocol is a class?
protocol Foo: class {}
extension Foo where Self : NSView {
func foo() {
// error: 'super' cannot be used outside of class members*
super.isFirstResponder
}
}
@DevAndArtist re init - I guess I use the term more generically than may be technically correct...
: class constraint is deprecated but not emitting any warning yet, the new way to express it is : AnyObject. However in my example it's an unnecessary constraint because in the extension it's already proven that we're inside a class.
Anyway, I'm just trying to find out if it's just a non-lifted limitation or if there are other technical issues which prevent this from working. ;)
FWIW, most of the time you could safely add setup code in awakeFromNib. Especially since then, AND ONLY THEN, is it guaranteed that all the Interface Builder linkages are properly initialized.
Before you call super.init, you must initialize all stored properties, but a protocol doesn't know what the conforming type's stored properties are going to be. So protocol extensions can only add convenience initializers.
Even if there were some way around that, protocols cannot provide @objc implementations, since the ObjC runtime finds methods differently than the Swift runtime.
So I'm afraid commonInit() is the best you can do without some significant (undesigned) changes to how Swift works.
What's the problem with awakeFromNib?
It's the common path that both inits will pass through, so you can remove init altogether.
If you're initializing variables, you could make them var name: Type! instead of let name: Type.
Programmatically created views as @ConfusedVorlon just mentioned don't get a call on awakeFromNib if they are not indeed created from a xib / storyboard. Furthermore I highly discourage you from writing Type! if it's not an outlet.