通知NSNotification和KVO的使用

1.通知NSNotification的使用
NSNotification的名称在整个项目中必须是唯一的
补充一个小知识,为了确保通知名称的唯一性,定义NSNotification的name时需要做些改变
前边定义时如下

#define AnyNotificationName   @"notiName"

最好写成

1 NSString * const AnyNotificationName = @"notiName";
2 //也可写成下面的方式,这是等价的。可以通过打印内存地址来比较
3 const NSString *AnyNotificationName = @"notiName";

因为#define本质上还是NSString *,它与NSString * const的区别在于NSString *的指针可以改变指向(虽然内容不会改变),而NSString * const就是指向、内容都无法改变,更安全。因此在定义一些全局唯一性的属性时,推荐该法。

更正:

*******************************************************

有时使用

const NSString *AnyNotificationName = @"notiName";

会给出警告sending 'const NSString *__strong' to parameter of type 'NSString' discards qualifiers
这时就需要写成

NSString * const AnyNotificationName = @"notiName";

前者相当于指针本身不可修改,后者表示指针指向的内容不可修改。这两种写法的作用都是使AnyNotificationName只可读不可写。

//指针本身不可变,写通知名称时推荐该法
NSString * const kSomeConstantString = @"";

//下边两种写法是等价的,表示指针指向的内容不可变。
const NSString * kSomeConstantString = @"";
NSString const * kSomeConstantString = @"";

*******************************************************

①使前用先注册监听者,在下例中,当有名字为AnyNotificationName的通知发送到通知中心NSNotificationCenter后,就执行centerActive方法

 1 NSString * const AnyNotificationName = @"notiName";
 2 
 3 /**
 4 * 在通知中心(NSNotificationCenter)中注册监听者
 5 *
 6 * 通知中心(NSNotificationCenter)中注册观察者
 7 * addObserver 注册的观察者
 8 *
 9 * selector 收到通知后执行的方法
10 * name     通知的名字,也是通知的唯一标识
11 * object   这里的object不是传递给监听者的数据,通常为nil
12 */
13 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(centerActive:) name:AnyNotificationName object:nil];

②使用完毕后要从NSNotificationCenter移除观察者

[[NSNotificationCenter defaultCenter] removeObserver:self name:AnyNotificationName object:nil];
1 ///接收通知中心发送的通知后执行的方法
2 -(void)centerActive:(NSNotification *) notification{
3     if ([notification.name isEqualToString:AnyNotificationName]) {
4         NSLog(@"通知中心发送的通知名称为:%@",notification.name);
5     }
6 }

③触发通知,在调用通知的时候会在整个项目中寻找符合该名称的通知,所以通知的name必须唯一

1 NSArray *aaa = @[@"me",@"you",@"him"];
2 //发送一个名为AnyNotificationName(notiName)的通知给观察者,这里的object才是传递给监听者的数据
3 [[NSNotificationCenter defaultCenter] postNotificationName:AnyNotificationName object:aaa];

下面是完整的例子

 1 NSString * const AnyNotificationName = @"notiName";
 2 
 3 @interface ViewController ()
 4 
 5 @end
 6 
 7 @implementation ViewController
 8 
 9 - (void)viewDidLoad {
10     [super viewDidLoad];
11     
12     UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
13     [btn setTitle:@"发送通知" forState:UIControlStateNormal];
14     [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
15     btn.frame = CGRectMake(100, 300, 100, 50);
16     [btn addTarget:self action:@selector(sendNotification) forControlEvents:UIControlEventTouchUpInside];
17     [self.view addSubview:btn];
18     
19 }
20 
21 /**
22  * 通知中心(NSNotificationCenter)中注册观察者
23  * addObserver 注册的观察者
24  *
25  * selector 收到通知后执行的方法
26  * name     通知的名字,也是通知的唯一标识
27  * object   这里不是传递给观察者的参数,通常为nil。
28  */
29 - (void)viewDidAppear:(BOOL)animated{
30     [super viewDidAppear:animated];
31 
32     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(centerActive:) name:AnyNotificationName object:nil];
33 }
34 
35 ///从通知中心(NSNotificationCenter)移除观察者
36 -(void)viewDidDisappear:(BOOL)animated{
37     [super viewDidDisappear:animated];
38     
39     [[NSNotificationCenter defaultCenter] removeObserver:self name:AnyNotificationName object:nil];
40 }
41 
42 ///接收通知中心发送的通知
43 -(void)centerActive:(NSNotification *) notification{
44     if ([notification.name isEqualToString:AnyNotificationName]) {
45         NSArray *a = notification.object;
46         NSLog(@"通知中心发送的通知名称为:%@,数组为=%@",notification.name,a);
47     }
48 }
49 
50 ///利用通知中心发送通知,同时传递数据
51 -(void)sendNotification{
52     NSArray *aaa = @[@"me",@"you",@"him"];
53     //发送一个名为AnyNotificationName(notiName)的通知给观察者
54     [[NSNotificationCenter defaultCenter] postNotificationName:AnyNotificationName object:aaa];
55 }
56 
57 @end

2.知道了NSNotification,下面介绍下KVO,也是用的观察者模式,包括注册观察者、注销观察者等。如下:
定义两个类,被观察者和观察者

1 /** 被观察者,定义一个被观察的属性 */
2 @interface KVOSubject : NSObject
3 @property(nonatomic,copy) NSString *changedStr;
4 @end
5 
6 /** 观察者 */
7 @interface KVObserver : NSObject
8 @end

在观察者KVObserve的.m中实现一个方法,这个方法主要是用来当被观察的值发生改变时进行的操作

1 -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
2     //获取属性改变后的新值
3     NSString *aaa = change[NSKeyValueChangeNewKey];
4     NSLog(@"值发生了改变");
5 }

然后就可以进行观察行为

 1 -(void)activeKVO{
 2     KVOSubject *kvoSub = [[KVOSubject alloc]init];//被观察者
 3     KVObserver *kvoObser = [[KVObserver alloc]init];//观察者
 4     //注册观察者,forKeyPath中为KVOSubject的property属性
 5     [kvoSub addObserver:kvoObser forKeyPath:@"changedStr" options:NSKeyValueObservingOptionNew context:nil];
 6     //底下俩方法都可以改变值,所以打印两次
 7     kvoSub.changedStr = @"这是改变后的值";
 8     [kvoSub setValue:@"这是改变后的值" forKey:@"changedStr"];
 9     //注销观察者
10     [kvoSub removeObserver:kvoObser forKeyPath:@"changedStr"];
11 }
原文地址:https://www.cnblogs.com/Apologize/p/4725059.html