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

iOS中如何正确初始化委托并实现Menu与MenuMainView的委托回调

解决Swift委托相关的两个初始化错误

先定义协议(满足需求的基础)

首先明确协议,确保Menu能响应MenuMainView的按钮点击事件:

protocol IChangeMenuItemHandler: AnyObject {
    func changeMenuItem()
}

错误1:Property 'self.delegate' not initialized at super.init call

问题原因

Swift要求子类的存储属性必须在调用super.init之前完成初始化,如果MenuMainView中delegate是未赋值的非可选存储属性,就会触发这个错误。另外,委托属性必须用weak修饰,避免循环引用。

解决方法

将delegate定义为弱引用可选类型(默认值为nil),这样无需在super.init前手动初始化,后续再赋值即可。完整的MenuMainView实现:

class MenuMainView: UIView {
    // 弱引用可选类型,默认nil,无需提前初始化
    weak var delegate: IChangeMenuItemHandler?
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupUI()
    }
    
    private func setupUI() {
        // 创建按钮并绑定点击事件
        let toggleButton = UIButton(type: .system)
        toggleButton.setTitle("切换菜单", for: .normal)
        toggleButton.addTarget(self, action: #selector(onToggleButtonTap), for: .touchUpInside)
        toggleButton.frame = CGRect(x: 50, y: 100, width: 200, height: 40)
        addSubview(toggleButton)
    }
    
    @objc private func onToggleButtonTap() {
        // 点击时触发委托方法
        delegate?.changeMenuItem()
    }
}

错误2:Variable 'self.menuView' used before being initialized

问题原因

在初始化menuView时直接传入self作为委托,此时self(即Menu实例)还未完成所有存储属性的初始化,Swift不允许在初始化完成前将self传递给其他对象。

解决方法

有两种常用方案:

方案1:使用隐式解包可选类型

将menuView定义为隐式解包可选,在Menu初始化完成后再创建menuView并赋值委托:

class Menu: UIViewController {
    // 隐式解包可选,允许延迟初始化
    private var menuView: MenuMainView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 此时self已完全初始化,可安全传递给delegate
        menuView = MenuMainView(frame: view.bounds)
        menuView.delegate = self
        view.addSubview(menuView)
    }
}

// 遵守协议实现方法
extension Menu: IChangeMenuItemHandler {
    func changeMenuItem() {
        // 这里写菜单切换的具体逻辑
        print("菜单切换事件触发")
    }
}

方案2:使用懒加载属性

通过lazy延迟初始化menuView,闭包执行时self已完成初始化:

class Menu: UIViewController {
    // 懒加载属性,第一次访问时才初始化
    private lazy var menuView: MenuMainView = {
        let view = MenuMainView(frame: view.bounds)
        view.delegate = self
        return view
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(menuView)
    }
}

extension Menu: IChangeMenuItemHandler {
    func changeMenuItem() {
        print("菜单切换事件触发")
    }
}

内容的提问来源于stack exchange,提问作者Steven Kirke

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 23:47:33