美文网首页
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