美文网首页
Swift Protocol

Swift Protocol

作者: YourSummer | 来源:发表于2022-06-15 16:52 被阅读0次

    - 用于通信

    一个简单的例子: 比如你封装了一个View, 需要回调出去一个按钮事件

    class TestView: UIView {
        // 注意这里要使用weak标记
        weak var delegate: TestViewProtocol?
        
        fileprivate lazy var iEnterBtn: UIButton = {
            let btn = UIButton()
            btn.addTarget(self, action: #selector(enterAction), for: .touchUpInside)
            return btn
        }()
        
        @objc func enterAction() {
            // 执行代理
            delegate?.didClickEnterButton()
        }
    }
    
    protocol TestViewProtocol: AnyObject {
        func didClickEnterButton()
    }
    

    实现

    class TestController: UIViewController {
        
        fileprivate lazy var iTestView: TestView = {
            let view = TestView()
            // 签代理
            view.delegate = self
            return view
        }()
        
        override func viewDidLoad() {
            super.viewDidLoad()
            view.addSubview(iTestView)
        }
    }
    
    extension TestController: TestViewProtocol {
        // 实现代理方法
        func didClickEnterButton() {
            print("触发点击事件")
        }
    }
    

    - 高阶使用

    第一个问题: 如何让多个对象能够实现同一个方法, 统一函数名称

    方法1: 基类+子类继承

    传统的实现方法, OC也适用

    • 定义基类
    • 子类继承自基类
    • 重写父类的方法
    class BaseView: UIView {
    
        // 根据传入的模型更新数据
        func updateView() { }
    }
    
    class TestView0: BaseView {
        // 重写更细试图的方法
        override func updateView() {
            
        }
    }
    
    class TestView1: BaseView {
        // 重写更细试图的方法
        override func updateView() {
            
        }
    }
    
    方法2: 在Swift中运用面向协议的思路
    • 声明协议与协议方法
    • 需要此方法的类实现协议方法
    protocol ViewProtocol: AnyObject {
        func updateView()
    }
    
    class TestView0: UIView {
         
    }
    
    // 把属于同一个协议的实现方法写一个扩展, 使代码结构清晰
    extension TestView0: ViewProtocol {
        func updateView() {
            
        }
    }
    
    class TestView1: UIView {
        
    }
    
    extension TestView1: ViewProtocol {
        
        func updateView() {
            
        }
    }
    

    第二个问题: 每个View都有对应的数据模型有更新UI的方法传值到View内部, 并给View相关控件赋值

    能不能做到更新UI的方法统一, 模型参数不同呢

    使用Protocol的关联属性

    协议声明

    protocol ViewProtocol: AnyObject {
        // 关联类型
        associatedtype T
        // 将关联的类型传入函数
        func updateView(model: T)
    }
    

    第一个测试View 数据模型为: Model_0

    // 示例模型0
    struct Model_0 {
        var name = ""
        var cover = ""
    }
    
    // 第一个View数据模型是 Model_0
    class TestView0: UIView {
         // 指明 关联类型是Model_0
         typealias T = Model_0
    }
    
    // 实现协议方法
    extension TestView0: ViewProtocol {
        func updateView(model: Model_0) {
            // 给控件赋值
        }
    }
    

    第二个测试View 数据模型为: Model_1

    // 示例模型1
    struct Model_1 {
        var name = ""
        var cover = ""
    }
    
    // 第二个View数据模型是 Model_1
    class TestView1: UIView {
         // 指明 关联类型是Model_1
        typealias T = Model_1
    }
    
    // 实现协议方法
    extension TestView1: ViewProtocol {
        func updateView(model: Model_1) {
            // 给控件赋值
        }
    }
    
    调用
    // 创建模型Model_0
    let model_0 = Model_0(name: "小明", cover: "http://xxx.com/xxxx")
    // 实例化View
    let testView_0 = TestView0()
    // View调用更新函数
    testView_0.updateView(model: model_0)
    
    
    
    // 创建模型 Model_1
    let model_1 = Model_1(name: "小明", cover: "http://xxx.com/xxxx")
    // 实例化View
    let testView_1 = TestView1()
    // View调用更新函数
    testView_1.updateView(model: model_1)
    

    第三个问题: 多个对象都必须执行一个相同的方法

    方式一: 每个对象内都去写这个方法实现, 会出现大量冗余重复的代码
    方式二: 使用协议扩展-添加默认协议方法的实现, 如下:

    协议扩展-添加默认实现

    • 声明协议
    protocol ViewProtocol: AnyObject {
        func defaultFunc()
    }
    
    • 扩展协议
    extension ViewProtocol where Self: UIView {
        
        func defaultFunc() {
            // 比如: 每个类调用的时候要上报给后端一个信息
            print("默认实现的方法")
        }
    }
    

    测试的两个View:

    // 遵守了协议, 但是不用实现协议方法
    class TestView_0: UIView, ViewProtocol {}
    class TestView_1: UIView, ViewProtocol {}
    

    调用:

    let testView_0 = TestView0()
    // 调用
    testView_0.defaultFunc()
    // 输出: 默认实现的方法
    
    let testView_1 = TestView1()
    // 调用
    testView_1.defaultFunc()
    // 输出: 默认实现的方法
    

    相关文章

      网友评论

          本文标题:Swift Protocol

          本文链接:https://www.haomeiwen.com/subject/otbomrtx.html