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

Swift 继承场景下父类如何向子类传递事件

实现方案

继承场景下父类向子类传递事件,优先使用模板方法模式实现,无需引入闭包、通知、代理等额外机制,完全贴合Swift面向对象的继承设计逻辑,具体实现如下:

  • 在父类中定义可被子类重写的事件钩子方法,把通用逻辑(比如dismiss相机)放在父类默认实现中
  • 父类收到系统的UIImagePickerController代理回调时,直接调用预先定义的钩子方法
  • 子类按需重写钩子方法,在重写逻辑中先调用super实现复用父类通用能力,再编写自身业务逻辑

代码实现

父类BaseViewController修改

class BaseViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
    func openCamera() {
        let picker = UIImagePickerController()
        picker.delegate = self
        picker.sourceType = .camera
        present(picker, animated: true)
    }
    
    /// 媒体选择完成钩子方法,子类可重写实现自定义业务
    func didFinishPickingMedia(_ picker: UIImagePickerController, info: [UIImagePickerController.InfoKey : Any]) {
        // 父类默认通用逻辑:关闭相机
        picker.dismiss(animated: true)
    }
    
    /// 相机取消钩子方法,子类可重写
    func didCancelPickingMedia(_ picker: UIImagePickerController) {
        picker.dismiss(animated: true)
    }

    // MARK: UIImagePickerControllerDelegate
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]){
        // 收到系统回调后,调用钩子方法,事件自动传递给重写该方法的子类
        didFinishPickingMedia(picker, info: info)
    }
    
    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        didCancelPickingMedia(picker)
    }
}

子类ViewController实现

class ViewController: BaseViewController {
    @IBAction func cameraButtonClicked(_ sender: Any) {
        self.openCamera()
    }
    
    // 重写父类钩子方法,接收媒体选择完成事件
    override func didFinishPickingMedia(_ picker: UIImagePickerController, info: [UIImagePickerController.InfoKey : Any]) {
        // 先调用父类实现,复用关闭相机的通用逻辑
        super.didFinishPickingMedia(picker, info: info)
        
        // 编写子类自定义业务逻辑,比如获取选中图片
        guard let originalImage = info[.originalImage] as? UIImage else { return }
        // 后续处理图片:展示、上传等
        print("子类已获取选中图片,尺寸为\(originalImage.size)")
    }
}

可选优化

如果需要强制所有继承自BaseViewController的子类必须实现媒体选择后的处理逻辑,可以将钩子方法的默认实现替换为:

func didFinishPickingMedia(_ picker: UIImagePickerController, info: [UIImagePickerController.InfoKey : Any]) {
    fatalError("子类必须重写`didFinishPickingMedia(_:info:)`方法实现自定义业务逻辑")
}

注意:该方式会在子类未重写方法时触发运行时崩溃,适合要求所有子类必须实现对应逻辑的场景,如果部分子类不需要处理相机回调,保留空的默认实现即可。

内容的提问来源于stack exchange,提问作者Vishal Desai

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 23:54:18