Short answer: The doStuff
method in
public extension UIView {
open func doStuff() {...}
}
has an effective access level "public" because the extension is
marked public. Therefore it cannot be overridden in a subclass.
Note that Xcode warns
warning: declaring instance method in PUBLIC extension
and the warning text should be (see below)
warning: declaring OPEN instance method in PUBLIC extension
To solve the problem, remove the public
access modifier of the extension:
extension UIView {
open func doStuff() {...}
}
Now the extension has the access level "open" (inherited from open class UIView
)
and the effective access level of doStuff
is "open" and it can be subclassed.
Longer answer:
Access Control in the Swift reference
states that
... you can mark an extension with an explicit access-level modifier ... to set a new
default access level for all members defined within the extension. This new default
can still be overridden within the extension for individual type members.
but actually you can only restrict type members within the extension to the same
or a lower access. Unfortunately, I could not find a definite reference for this
fact in the documentation.
SE-0117 Allow distinguishing between public access and public overridability
states that
For example, the true access level of a type member is computed as the minimum of the
true access level of the type and the declared access level of the member. If the class
is public but the member is open, the true access level is public.
but does not explain how this applies to extensions.
The check can be seen in the compiler source code
TypeCheckAttr.cpp.
If the access level of an item is larger then the access level of the containing
extension then the
diag::access_control_ext_member_more
diagnostic message is emitted:
WARNING(access_control_ext_member_more,none,
"declaring %select{PRIVATE|a fileprivate|an internal|a public}0 %1 in "
"%select{a private|a fileprivate|an internal|PUBLIC}2 extension",
(Accessibility, DescriptiveDeclKind, Accessibility))
Note that the "open" level is missing in the selection, and that is why it is missing in
warning: declaring instance method in PUBLIC extension