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
相关产品推荐
相关产品推荐

