iOS开发 通知、kvc、kvo、代理之间的区别与联系并使用oc语言举例说明

104 阅读3分钟

在iOS开发中,通知(Notification)、键值编码(KVC)、键值观察(KVO)和代理(Delegate)是四种常见的设计模式和通信机制。它们各自有独特的特点和适用场景,同时也有一定的联系。以下将从它们的区别与联系出发,并结合OC语言示例进行说明。

1. 通知(NSNotification)

特点:

  • 一对多通信:通知允许一个对象向多个接收者发送消息,适用于解耦的场景。
  • 全局通知:通过NSNotificationCenter管理,可以在整个应用范围内发送和接收通知。
  • 灵活性:可以携带自定义信息,但无法直接返回结果。

适用场景:

  • 控制器之间传递事件信息。
  • 视图模型层与控制器层之间的通信。

示例代码:

// 发送通知

NSNotification *notification = [NSNotification notificationWithName:@"MyNotification" object:self];

[[NSNotificationCenter defaultCenter] postNotification:notification];

// 接收通知

[[NSNotificationCenter defaultCenter] addObserver:self

selector:@selector handleNotification:]

name:@"MyNotification"

queue:nil];

- (void)handleNotification:(NSNotification *)notification {

NSLog(@"Received notification");

}

2. 键值编码(KVC)

特点:

  • 间接访问对象属性:通过字符串键名访问对象的属性,无需调用getter或setter方法。
  • 动态性:支持动态修改属性值,但编译时无法检查错误。
  • 效率较低:相比直接调用方法,性能稍低。

适用场景:

  • 动态属性操作,如数据绑定。
  • 简化代码,减少重复的getter/setter方法。

示例代码:

// 设置属性值

self.myProperty = @"Hello"; // 直接调用

[self setValue:@"Hello" forKey:@"myProperty"]; // KVC方式

// 获取属性值

NSString *value = self.myProperty; // 直接调用

NSString *kvcValue = [self valueForKey:@"myProperty"]; // KVC方式

3. 键值观察(KVO)

特点:

  • 观察者模式:允许对象监听其他对象的属性变化,并在变化时触发回调。
  • 动态性:通过运行时机制实现,无需修改被观察对象的代码。
  • 灵活性:支持单对多关系,但需要手动注册和注销观察者。

适用场景:

  • 视图模型层与控制器层之间的通信。
  • 实现MVC或MVVM架构中的数据绑定。

示例代码:

// 注册观察者

[self addObserver:self forKeyPath:@"myProperty"

changeHandler:^(id obj, NSKeyValueChange change, NSKeyValueChangeReason reason, NSKeyValueChangeContext *context) {

NSLog(@"Property changed");

}];

// 观察属性变化

- (void)observeValueForKeyPath:(NSString *)keyPath

ofObject:(id)object

change:(NSDictionary *)change

context:(void *)context {

NSLog(@"Received change for keyPath: %@", keyPath);

}

// 移除观察者

[self removeObserver:self forKeyPath:@"myProperty"];

4. 代理(Delegate)

特点:

  • 一对一通信:通常用于两个对象之间的协作,调用方通过协议定义方法,被调用方实现这些方法。
  • 严格耦合:代理模式要求调用方和被调用方之间有明确的接口约定。
  • 灵活性:可以返回值,便于控制流程。

适用场景:

  • 视图控制器与模型之间的交互。
  • 实现复杂的业务逻辑。

示例代码:

// 定义协议

@protocol MyDelegate

- (void)actionCompleted;

@end

// 实现协议

@interface MyViewController : UIViewController

@end

// 使用代理

- (void)doSomething {

MyViewController *vc = [[MyViewController alloc] init];

vc.delegate = self;

[vc performTask];

}

- (void)actionCompleted {

NSLog(@"Action completed");

}

区别与联系

  1. 区别:
  • 通知:一对多通信,全局通知,适用于解耦场景。
  • KVC/KVO:键值操作,KVC用于动态访问属性,KVO用于监听属性变化。
  • 代理:一对一通信,严格耦合,适用于协作场景。
  1. 联系:
  • 通知与KVO:都可以用于对象间的通信,但通知更适用于全局通信,而KVO更适合细粒度的属性监听。
  • 代理与KVO:代理模式可以替代KVO的部分功能,尤其是在需要返回值或控制流程的场景中。

总结

在实际开发中,选择合适的设计模式和通信机制需要根据具体需求来决定。例如,在需要解耦的场景中优先考虑通知;在需要细粒度监听属性变化时选择KVO;在需要严格控制流程时使用代理。通过合理结合这些模式,可以提高代码的可读性和可维护性。