I want to use one initializer or the other depending on the iOS version. If it is not iOS 14, I want to set the action to use later. My call to the super constructor happens inside an if/else:
class Control: UIControl {
var action: (() -> Void)?
init(action: @escaping () -> Void) {
self.action = action
if #available(iOS 14.0, *) {
let primaryAction = UIAction(handler: { _ in action() })
super.init(frame: .zero, primaryAction: primaryAction)
} else {
super.init(frame: .zero)
}
}
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
The call is:
let controlThatDoesNotWork = Control(action: { print("this doesn not work") })
The build error is
error: must call a designated initializer of the superclass 'UIControl'
super.init(frame: .zero, primaryAction: primaryAction)
^
Any idea how I need to call this convenience initializer so it builds?
Your
init(action: @escaping () -> Void)is a designated initializer, and designated initializers are not allowed to call convenience initializers from the base class, they must call another designater initializer.This is enforced here:
This the base initializer in discussion:
So, you need to convert your initializer to a convenience one, and have to call with
selfinstead ofsuperthe other intializers (again, due to the initializer rules):Alternatively, as adding a new subclass of
UIControlwill force all your custom classes to derive from that one, you could extend theUIControlwith a new convenience initializer: