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+ 支持。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐