KVO vs NSNotification vs 协议委托

作者:编程家 分类: ios 时间:2025-09-12

KVO vs NSNotification vs 协议/委托?

在iOS开发中,我们经常需要在对象之间进行通信和数据传递。为了实现这一目的,有几种常用的方式可以选择,包括KVO(Key-Value Observing),NSNotification和协议/委托模式。本文将比较这三种方式的使用场景、优缺点以及适用性,并提供相应的案例代码。

KVO(Key-Value Observing)

KVO是一种观察者模式,通过观察对象的属性变化来实现通信和数据传递。当观察的属性发生变化时,注册的观察者将收到通知,并执行相应的操作。KVO适用于需要监听对象属性变化的场景,例如当某个对象的属性发生变化时,需要触发其他对象执行相应操作。

KVO的使用相对简单,只需要在观察者对象中注册对应的属性即可。下面是一个使用KVO的示例代码:

swift

class Person: NSObject {

@objc dynamic var name: String = ""

}

class Observer: NSObject {

var person: Person

init(person: Person) {

self.person = person

super.init()

person.addObserver(self, forKeyPath: "name", options: [.new], context: nil)

}

deinit {

person.removeObserver(self, forKeyPath: "name")

}

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {

if keyPath == "name" {

if let newName = change?[.newKey] as? String {

print("New name: \(newName)")

}

}

}

}

let person = Person()

let observer = Observer(person: person)

person.name = "John" // Output: New name: John

在上面的例子中,我们创建了一个Person类,并在其中定义了一个name属性。然后我们创建了一个Observer类,并在其初始化方法中注册了对Person对象name属性的观察。当Person对象的name属性发生变化时,Observer对象将收到通知,并输出新的name值。

NSNotification

NSNotification是一种发布-订阅模式,通过通知中心来实现对象之间的通信和数据传递。当发布者发送一个通知时,所有订阅了该通知的观察者都将收到通知,并执行相应的操作。NSNotification适用于需要多对多通信的场景,例如一个操作需要通知多个对象进行相应处理。

NSNotification的使用相对灵活,需要定义通知名称,并在观察者对象中注册对应的通知。下面是一个使用NSNotification的示例代码:

swift

extension Notification.Name {

static let nameDidChange = Notification.Name("nameDidChange")

}

class Person {

var name: String = "" {

didSet {

NotificationCenter.default.post(name: .nameDidChange, object: self, userInfo: ["newName": name])

}

}

}

class Observer {

init() {

NotificationCenter.default.addObserver(self, selector: #selector(nameDidChange(_:)), name: .nameDidChange, object: nil)

}

deinit {

NotificationCenter.default.removeObserver(self)

}

@objc func nameDidChange(_ notification: Notification) {

if let newName = notification.userInfo?["newName"] as? String {

print("New name: \(newName)")

}

}

}

let person = Person()

let observer = Observer()

person.name = "John" // Output: New name: John

在上面的例子中,我们创建了一个Person类,并在其中定义了一个name属性。当name属性发生变化时,我们使用NotificationCenter发送一个名为nameDidChange的通知,并携带新的name值。然后我们创建了一个Observer类,并在其初始化方法中注册对nameDidChange通知的观察。当Person对象的name属性发生变化时,Observer对象将收到通知,并输出新的name值。

协议/委托模式

协议/委托模式是一种对象之间的通信方式,通过定义协议和委托来实现。一个对象可以委托给另一个对象执行特定的操作,当需要执行该操作时,委托对象将调用委托方定义的方法。协议/委托模式适用于需要一个对象代表另一个对象执行特定任务的场景。

协议/委托模式的使用相对灵活,需要定义协议,并在委托对象中声明委托方法。下面是一个使用协议/委托模式的示例代码:

swift

protocol PersonDelegate: AnyObject {

func nameDidChange(newName: String)

}

class Person {

weak var delegate: PersonDelegate?

var name: String = "" {

didSet {

delegate?.nameDidChange(newName: name)

}

}

}

class Observer: PersonDelegate {

func nameDidChange(newName: String) {

print("New name: \(newName)")

}

}

let person = Person()

let observer = Observer()

person.delegate = observer

person.name = "John" // Output: New name: John

在上面的例子中,我们定义了一个PersonDelegate协议,并在其中声明了nameDidChange方法。然后我们创建了一个Person类,并在其中定义了一个delegate属性用于委托。当name属性发生变化时,我们调用delegate对象的nameDidChange方法。然后我们创建了一个Observer类,并实现了PersonDelegate协议的nameDidChange方法。将Observer对象设置为Person对象的delegate后,当Person对象的name属性发生变化时,Observer对象将执行nameDidChange方法,并输出新的name值。

KVO、NSNotification和协议/委托模式都是在iOS开发中常用的对象通信和数据传递方式。它们各自适用于不同的场景,选择合适的方式取决于具体需求。KVO适用于需要监听对象属性变化的场景;NSNotification适用于多对多通信的场景;协议/委托模式适用于需要一个对象代表另一个对象执行特定任务的场景。根据具体情况选择合适的方式,可以提高代码的可读性和可维护性。