Swift自定义UIControl子类调用父类构造器报指定初始化错误如何解决
错误原因
Swift 类初始化规则明确要求:子类的指定初始化器必须直接调用父类的指定初始化器,不能调用父类的便利初始化器。
你用到的 UIControl.init(frame:primaryAction:) 是iOS 14新增的便利构造器,不属于UIControl的指定构造器范畴,因此直接在子类指定构造器中调用会触发编译错误。
修复方案
调整初始化逻辑:统一先调用父类的指定初始化器super.init(frame: .zero),iOS 14及以上版本在初始化完成后再为实例添加UIAction即可,不需要在构造器阶段调用父类便利构造器。同时可以补全低于iOS 14版本的事件触发逻辑,完整可运行代码如下:
class Control: UIControl { var action: (() -> Void)? init(action: @escaping () -> Void) { self.action = action // 先调用父类指定初始化器,符合Swift初始化规则 super.init(frame: .zero) if #available(iOS 14.0, *) { let primaryAction = UIAction(handler: { _ in action() }) // 初始化完成后添加UIAction,效果和调用便利构造器一致 addAction(primaryAction, for: .touchUpInside) } else { // 低iOS版本兼容:添加target触发自定义动作 addTarget(self, action: #selector(triggerAction), for: .touchUpInside) } } override init(frame: CGRect) { super.init(frame: frame) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } @objc private func triggerAction() { action?() } }
原有调用代码无需修改即可正常运行:
let controlThatWork = Control(action: { print("this works now") })
补充说明
如果你确实需要使用父类的便利构造器,也可以将子类的init(action:)声明为便利构造器,但这种方案需要额外处理属性初始化逻辑,复杂度更高,不如上述方案简洁通用。
内容的提问来源于stack exchange,提问作者regina_fallangi
相关产品推荐
相关产品推荐

