面试题答案
一键面试- 基本KVO监听
City
属性变化- 首先,确保相关类继承自
NSObject
(在Objective - C中,KVO基于NSObject
的键值观察机制)。 - 在持有
Person
对象的类中,注册KVO监听:
- (void)viewDidLoad { [super viewDidLoad]; Person *person = [[Person alloc] init]; [person addObserver:self forKeyPath:@"address.city" options:NSKeyValueObservingOptionNew context:nil]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context { if ([keyPath isEqualToString:@"address.city"]) { NSString *newCity = change[NSKeyValueChangeNewKey]; NSLog(@"City has changed to: %@", newCity); } } - (void)dealloc { [self.person removeObserver:self forKeyPath:@"address.city"]; }
- 在Swift中:
class ViewController: UIViewController { var person: Person! override func viewDidLoad() { super.viewDidLoad() person = Person() person.addObserver(self, forKeyPath: "address.city", options:.new, context: nil) } override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { if keyPath == "address.city" { if let newCity = change?[.newKey] as? String { print("City has changed to: \(newCity)") } } } deinit { person.removeObserver(self, forKeyPath: "address.city") } }
- 首先,确保相关类继承自
- 处理对象关系动态变化(如
Address
对象被替换)- Objective - C:
- 当
Address
对象可能被替换时,除了监听address.city
,还需要监听address
本身的变化。 - 注册对
address
的监听:
- (void)viewDidLoad { [super viewDidLoad]; Person *person = [[Person alloc] init]; [person addObserver:self forKeyPath:@"address.city" options:NSKeyValueObservingOptionNew context:nil]; [person addObserver:self forKeyPath:@"address" options:NSKeyValueObservingOptionNew context:nil]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context { if ([keyPath isEqualToString:@"address"]) { // 移除旧的`address.city`监听 Address *oldAddress = change[NSKeyValueChangeOldKey]; if (oldAddress) { [oldAddress removeObserver:self forKeyPath:@"city"]; } // 添加新的`address.city`监听 Address *newAddress = change[NSKeyValueChangeNewKey]; if (newAddress) { [newAddress addObserver:self forKeyPath:@"city" options:NSKeyValueObservingOptionNew context:nil]; } } else if ([keyPath isEqualToString:@"address.city"]) { NSString *newCity = change[NSKeyValueChangeNewKey]; NSLog(@"City has changed to: %@", newCity); } } - (void)dealloc { [self.person removeObserver:self forKeyPath:@"address.city"]; [self.person removeObserver:self forKeyPath:@"address"]; }
- 当
- Swift:
class ViewController: UIViewController { var person: Person! override func viewDidLoad() { super.viewDidLoad() person = Person() person.addObserver(self, forKeyPath: "address.city", options:.new, context: nil) person.addObserver(self, forKeyPath: "address", options:.new, context: nil) } override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { if keyPath == "address" { if let oldAddress = change?[.oldKey] as? Address { oldAddress.removeObserver(self, forKeyPath: "city") } if let newAddress = change?[.newKey] as? Address { newAddress.addObserver(self, forKeyPath: "city", options:.new, context: nil) } } else if keyPath == "address.city" { if let newCity = change?[.newKey] as? String { print("City has changed to: \(newCity)") } } } deinit { person.removeObserver(self, forKeyPath: "address.city") person.removeObserver(self, forKeyPath: "address") } }
- Objective - C:
这样在City
属性变化以及Address
对象被替换时,都能通过KVO正常监听并处理变化。