1.定义协议
protocol ProVBDelegate:AnyObject { func back(data:String) }
AnyObject 作用是提示这个代理只能被类使用 (不能使用 weak)
如果代理方法是可选的需要这样实现如下
@objc protocol ProVBDelegate:AnyObject { @objc optional func back(data:String) }
2.委托方(委托持有者)
(1)声明代理属性 (结构体的时候 不使用weak )
weak var proVBDelegate:ProVBDelegate?
(2)需要的时候调用协议方法
proVBDelegate?.back?(data: "传递的参数")
3.代理方
(1)跳转的地方设置代理
@objc func sendData() { // 跳转到ProtocolViewControllerB let vcB = ProtocolViewControllerB() vcB.proVBDelegate = self navigationController?.pushViewController(vcB, animated: true) }
(2)最好写一个 extension 继承代理 实现代理方法 代码整洁可维护性高
extension ProtocolViewControllerA:ProVBDelegate{ func back(data: String) { print("VB2传递过来的参数\(data)") } }
代理循环引用
- ARC 内存管理基础
Swift 使用自动引用计数(ARC)来管理内存
每个对象都有一个引用计数器
当引用计数为 0 时,对象会被销毁
循环引用会导致双方引用计数都无法归零
- 循环引用形成的典型场景
swift
class ViewController {
var delegate: SomeDelegate? // 强引用
}
class DataModel: SomeDelegate {
var controller: ViewController? // 强引用
init() {controller = ViewController()controller?.delegate = self // 互相强引用!
}
}
3.为什么weak 可以避免循环引用
weak 的实现机制:
不增加引用计数
(1)weak 引用不会增加对象的引用计数
当对象被释放时,weak 引用会自动变为 nil
(2)Swift Runtime 的实现:
weak 引用实际上是一个指向对象侧表(side table) 的指针
侧表包含对象的弱引用计数等信息
当强引用计数为 0 时,对象内存被释放,所有弱引用自动置为 nil
4.delegate 跟 闭包比 的优点缺点
Swift 代理与闭包的对比
代理模式 (Delegate Pattern)
优点
职责分离清晰 - 将功能委托给专门的类,符合单一职责原则
协议约束 - 通过协议强制实现必需方法,编译器可检查
可维护性强 - 接口明确,代码结构清晰
多对一关系 - 一个代理可为多个对象服务
避免循环引用 - 使用 weak引用可避免内存泄漏
可扩展性 - 可定义可选方法,通过协议扩展提供默认实现
缺点
代码量多 - 需要定义协议和实现类
相对繁琐 - 简单的回调场景显得过于复杂
传递链复杂 - 多层传递时代理链可能较长
闭包 (Closure)
优点
简洁灵活 - 代码紧凑,适合简单回调
上下文捕获 - 自动捕获上下文变量
即用即写 - 不需要单独定义协议和方法
链式调用 - 适合链式操作和函数式编程
异步友好 - 在异步编程中表达清晰
缺点
循环引用风险 - 需要手动使用 [weak self]等避免
可读性降低 - 复杂逻辑写在闭包中可能难以维护
调试困难 - 堆栈跟踪不如方法调用清晰
类型安全 - 需要明确定义闭包类型,否则编译器提示有限
5.代理跟 通知比较优点缺点
通知模式 (Notification Pattern)
优点
完全解耦 - 发送者和接收者无需相互知道对方的存在
一对多广播 - 一个通知可以被多个观察者接收
全局通信 - 适合应用级别的全局事件
跨模块通信 - 不同模块间通信的理想选择
灵活性高 - 可动态添加/移除观察者
缺点
类型不安全 - 传递的数据是 Any?类型
编译时不检查 - 拼写错误不会在编译时发现
难以调试 - 通知链路复杂时难以追踪
内存管理 - 需要手动移除观察者
可读性差 - 通知名通常为字符串常量
代理模式 (Delegate Pattern) - 回顾
优点
类型安全,编译时检查
接口明确,代码结构清晰
避免循环引用
可扩展性强
缺点
一对一关系(通常)
发送者和接收者需要相互引用
代码量较多