You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 04:09:04