码迷,mamicode.com
首页 > 其他好文 > 详细

NSNotification、KVC及KVO

时间:2015-07-29 21:17:30      阅读:98      评论:0      收藏:0      [点我收藏+]

标签:nsnotification nsnot

通知

了解:

NSNotification objects encapsulate information so that it can be broadcast to other objects by an NSNotificationCenter object. An NSNotification object (referred to as a notification) contains a name, an object, and an optional dictionary. The name is a tag identifying the notification. The object is any object that the poster of the notification wants to send to observers of that notification (typically, it is the object that posted the notification). The dictionary stores other related objects, if any. NSNotification objects are immutable objects.
一个通知对象包含有一些信息,以至它可以通过通知中心对象广播给其他对象,一个消息通知对象(一个通知)包含有一个名称,一个对象,可一个操作字典。名称是一个通知对象的标识符,对象是可以是任何对象,只要是通知发送者想发送给通知观察者(简单来说就是通知发送者)。如果有则字典中存储的是一些相关的对象。NSNotification对象是不可变的对象。


You can create a notification object with the class methods notificationWithName:object: or notificationWithName:object:userInfo:. However, you don’t usually create your own notifications directly. The NSNotificationCenter methods postNotificationName:object: and postNotificationName:object:userInfo: allow you to conveniently post a notification without creating it first.
可以通过notificationWithName:object: 或notificationWithName:object:userInfo:然而你不必要直接去创建自己的通知。通知中心的方法postNotificationName:object: 和 postNotificationName:object:userInfo:允许你很方便的在没有创建之前发出一个通知。


使用通知一定要保证在发送之前要注册好通知,不然没有对象可以接收这个通知。


    NSDictionary *dict = @{@"name":@"lius",@"age":@12};
    NSNotification *first = [NSNotification notificationWithName:@"firstNotification" object:self userInfo:dict]; // 为self创建一个通知对象,self将发出通知

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveNotification) name:@"firstNotification" object:nil]; // 将通知加入到通知中心,这样就会有方法来接收self发出的通知
    [[NSNotificationCenter defaultCenter] postNotification:first]; // 发出通知


对比:notificationWithName: object: userInfo    与 addObserver: selector:name:object
两个name:指的是同一个对象,通知的名称,第一个是创建一个通知,给通知命名,第二个是添加一监听监听某个通知。 如果第二个名字为nil就不以此为判断。
两个object:代表是哪个对象发出的通知对象,第一个创建一个通知,为某个对象创建一个通知,第二个为监听某个对象发送过来的通知。


通知中心


1. 通知中心:
通知中心实际上是在程序内部提供了消息广播的一种机制。通知中心不能在进程间通信。实际上就是一个二传手,把接收到的消息,根据内部的一个消息转发表,来将消息转发给需要的对象。通知中心是基于观察者模式的,它允许注册、删除观察者。
一个NSNotificationCenter可以有许多的通知消息NSNotification,对于每一个NSNotification可以有很多的观察者Observer来接收通知。


2. 通知中心两个重要类
NSNotificationCenter:这是iOS中通知中心的灵魂,由该类实现了观察者模式,并给开发者提供了诸如注册、删除观察者的接口,我们可以通过一个单例来获得它的实例(一个程序内部只有一个NSNotificationCenter实例对象)。
NSNotification:这是消息携带的载体,通过它可以将消息内容传递给观察者。其中。name对应消息名称标识,object一般是发送者本身、dictionary则是传递的消息内容。


3. 通知中心的使用
当我们注册了某个消息的观察者后,如果有了对应的消息,则观察者会收到相应的消息,并展开处理。这里需要注意的是,当使用完消息后,不想再接收到消息,则需要把观察者移除,否则会出现错误。


添加时机:想监听消息时
移除时机:当使用完消息后,不想再接收到消息。在不需要时如果不移除信息会出现错误。


注册通知:即要在什么地方接受通知
- (void)addObserver:(id)notificationObserver
           selector:(SEL)notificationSelector
               name:(NSString *)notificationName
             object:(id)notificationSender
参数:
notificationObserver:注册观察者的一个对象,值一定不能是nil(一般为控制器)
notificationSelector:方法明确叙述这个信息,接收者发送通知监听者***。这个方法规定只能传入一个参数,并且这个参数是一个NSNotification类型的实例。简单来说就是回调方法。
notificationName:注册观察者的通知的名称,只有是此名称的通知才会被传送到观察者上。如果传入一个nil,通知中心将不会使用通知的名称来决定是否向其观察者传入一个通知。
notificationSender:这个对象用来说明观察者想接收哪个对象发来的通知,如果传入一个nil通知中心将不会使用一个通知发送者来决定是否向其观察者传送一个通知。简单来说就是谁发出的通知


通知注意点:
如果调用了addobserver:selector:name:object: 注意在观察者或是在相关的object销毁之前一定要调用removeObserver:name:object:




例子:


    self.p1 = [[Person alloc] init];
    self.p2 = [[Person alloc] init];
    
    NSDictionary *dict = @{@"name":@"lius",@"age":@12};
    NSDictionary *dict2 = @{@"name":@"hua",@"age":@13};
    
    // object为向某个对象添加通知,name为本通知的名称,两者的添加是为了后来监听做准备,监听需要知道要监听哪个对象或是哪个对象的哪个通知。
    NSNotification *first = [NSNotification notificationWithName:@"firstNotification" object:self.p1 userInfo:dict]; // self.p1发出通知,通知内容为字典dict
    NSNotification *second = [NSNotification notificationWithName:@"secondNotification" object:self.p2 userInfo:dict2];
    
    self.first = first;
    self.second = second;
    
    // 添加监听:name为通知的名称,object为发出通知的对象,如果name与object均为nil则所有的通知都会监听到
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveNotification:) name:nil object:nil]; 
  //  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveNotification:) name:second.name object:nil];


- (void)click
{
    
    // 发送两个通知,但只有几个对象是可以接收到的
    [[NSNotificationCenter defaultCenter] postNotification:self.first];
    [[NSNotificationCenter defaultCenter] postNotification:self.second];
    
    
}


- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}


KVC


NSKeyValueCoding,一个非正式的Protocol,提供一种机制来间接访问对象的属性。KVO就是基于KVC实现的关键技术之一。
理解:一个对象拥有某些属性。如:person对象有一个name和address属性。以KVC的说法,Person对象分别有一个value对应它的name和adderss的key值key是一个字符串,它对应的值可以是任意odgar对象。从最基础的层次上看,KVC有两个方法:一个是设置key的值,另一个是获取key的值。


//using the KVC accessor(getter)method
NSString *originalName = [p valueForKey:@“name”];


// using the KVC accessor(setter)method
[p setValue:@“newName” forKey:@“name”];


如果person 还有另一个key配偶(spouse),spouse的key值是另外一个Person对象,用KVC可以这样写
NSString *spousesName = [p valueForKeyPath:@“spouse.name”];


【注意:key与keyPath要区分开,key可以从一个对象中获取值,而keyPath可以将多个key用点号“.”分割连接起来】如上例:相当于
[[p valueForKey:@“spouse”] valueForKey:@“name”];


使用setvaluesForKey注意点: 当使用setvaluesForKeyWithDictionary这个函数时,如果字典中的值比成员变量的多就需要去考虑设置setValue:forUndefinedKey:而且在pugmkh,字典中有几个多余的key就会调用几次。  而且属性与key要保持一致,不然是无法匹配的,如果字典中key为name,则属性占要为@property(nonatomic,copy)NSString *name;


KVO


Key-Value Observing(KVO)建立在KVC之上,它能够观察一个对象的KVC key path值的变化,
需要注意三个方法:一个是在其中添加监听,一个是监听到改变后需要处理的方法,最后一个移除监听。  如果需要监听的对象比较多可以通过将添加了监听的对象放到数组中,然后在移除监听进按序移除。如果少移除了就会现crash


系统框架已经支持KVO,使用步骤为:
1. 注册,指定被观察者的属性。
2. 实现回调方法
3. 移除观察


例子:
- (void)viewDidLoad
{
    [super viewDidLoad];
    name = @"海线";
    price = 10.0;
    
    UILabel *priceLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 80, 80, 30)];
    priceLabel.text = [NSString stringWithFormat:@"%.2f",price];
    [self.view addSubview:priceLabel];
    self.myLabel = priceLabel;
    
// 添加到值的监听
    [self addObserver:self forKeyPath:@"price" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil ];
    
    
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    button.frame = CGRectMake(30, 190, 130, 50);
    [button addTarget:self action:@selector(btnClick) forControlEvents:UIControlEventTouchUpInside];
    [button setTitle:@"点击" forState:UIControlStateNormal];
    [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [self.view addSubview:button];
    
}


// 监听到对象改变后开始执行此方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"price"]) {
        self.myLabel.text = [NSString stringWithFormat:@"%.2f",price];
    }
}


- (void)btnClick
{
    NSNumber *value = @(arc4random() % 80);
    [self setValue:value forKey:@"price"];


}


在dealloc中释放


- (void)dealloc
{
   [self removeObserver:self forKeyPath:@"price"];  
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

NSNotification、KVC及KVO

标签:nsnotification nsnot

原文地址:http://blog.csdn.net/linfengwenyou/article/details/47133543

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!