【iOS开发基础】观察者模式
·
Delegate
在iOS开发中,delegate是一种常见的设计模式,主要用于对象之间的通信。通过delegate,一个对象可以将某些任务或事件的处理委托给另一个对象来完成。
定义delegate通常需要以下步骤:
protocol MyDelegate: AnyObject {
func didCompleteTask(result: String)
}
class TaskHandler {
weak var delegate: MyDelegate?
func performTask() {
let result = "Task completed"
delegate?.didCompleteTask(result: result)
}
}
class ViewController: UIViewController, MyDelegate {
let handler = TaskHandler()
override func viewDidLoad() {
super.viewDidLoad()
handler.delegate = self
}
func didCompleteTask(result: String) {
print(result)
}
}
delegate模式的特点是:
- 通常是一对一的关系
- 需要明确定义协议方法
- 使用weak引用避免循环引用
- 适用于需要明确指定处理对象的场景
观察者设计模式
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。当主题对象状态发生变化时,会通知所有观察者对象。
iOS中实现观察者模式的常见方式:
// NotificationCenter方式
NotificationCenter.default.addObserver(
self,
selector: #selector(handleNotification),
name: .myNotification,
object: nil
)
@objc func handleNotification() {
print("Received notification")
}
// KVO方式
class MyObject: NSObject {
@objc dynamic var value: Int = 0
}
let object = MyObject()
let observer = object.observe(\.value, options: [.new]) { _, change in
print("Value changed to \(change.newValue ?? 0)")
}
观察者模式的特点是:
- 通常是一对多的关系
- 观察者不需要知道具体发布者
- 可以通过多种方式实现(NotificationCenter、KVO等)
- 适用于需要广播通知的场景
对比与联系
两种模式都用于对象间通信,但有明显区别:
delegate更适合:
- 需要明确处理对象的场景
- 一对一的关系
- 需要返回结果或确认的情况
- 代码结构更清晰,责任明确
观察者模式更适合:
- 需要广播通知的场景
- 一对多的关系
- 松散耦合的情况
- 不需要知道具体接收者的情况
实际开发中常常结合使用两种模式。例如UITableView同时使用delegate处理用户交互,又使用数据源模式获取数据,而数据变更可以通过观察者模式通知相关视图更新。
// 结合使用示例
class DataManager {
static let dataUpdated = Notification.Name("DataUpdated")
func updateData() {
NotificationCenter.default.post(name: DataManager.dataUpdated, object: nil)
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(
self,
selector: #selector(reloadData),
name: DataManager.dataUpdated,
object: nil
)
}
@objc func reloadData() {
tableView.reloadData()
}
}
iOS 提供了多种方式实现观察者模式,其中 KVO(Key-Value Observing)是最常用的封装 API。以下是具体实现方式和相关细节:
KVO(Key-Value Observing)
KVO 是 iOS 原生支持的观察者模式实现,基于键值编码(KVC)机制。通过监听对象属性的变化触发回调。
注册观察者
[self.target addObserver:self
forKeyPath:@"propertyName"
options:NSKeyValueObservingOptionNew
context:nil];
实现回调方法
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary<NSKeyValueChangeKey,id> *)change
context:(void *)context {
if ([keyPath isEqualToString:@"propertyName"]) {
id newValue = change[NSKeyValueChangeNewKey];
// 处理变化
}
}
移除观察者
[self.target removeObserver:self forKeyPath:@"propertyName"];
NSNotificationCenter
另一种观察者模式实现,用于跨组件通信,不依赖属性监听。
发送通知
[[NSNotificationCenter defaultCenter] postNotificationName:@"NotificationName" object:nil];
注册观察者
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleNotification:)
name:@"NotificationName"
object:nil];
处理通知
- (void)handleNotification:(NSNotification *)notification {
// 处理通知
}
移除观察者
[[NSNotificationCenter defaultCenter] removeObserver:self];
Swift 中的 Property Observers
Swift 原生支持属性观察器,适用于同一类内部的属性监听。
var observedProperty: Int = 0 {
didSet {
print("属性从 \(oldValue) 变为 \(observedProperty)")
}
}
Combine 框架(iOS 13+)
现代响应式编程方案,提供更灵活的观察者模式实现。
import Combine
class MyClass {
@Published var observedProperty: Int = 0
private var cancellables = Set<AnyCancellable>()
init() {
$observedProperty
.sink { newValue in
print("属性变化: \(newValue)")
}
.store(in: &cancellables)
}
}
注意事项
KVO 需要手动管理观察者生命周期,确保在适当时候移除观察避免内存泄漏。Swift 中使用 KVO 需标记为 @objc dynamic 属性。NSNotificationCenter 更适合松散耦合的组件间通信。Combine 框架提供更现代化的解决方案但需要 iOS 13+ 支持。
更多推荐
所有评论(0)