美文网首页iOS DeveloperiOS奇淫巧技iOS 开发
IOS 通知详解+异步发送和接收通知

IOS 通知详解+异步发送和接收通知

作者: MrLiangC | 来源:发表于2016-09-14 15:10 被阅读2842次

一、通知的基本使用

每一个应用程序都有一个通知中心,专门负责协助不同 对象之间的消息通信。

任何一个对象都可以向通知中心发布通知,描述自己在做什么。其他感兴趣的对象可以申请在某个特定通知发布时(或在某个特定的对象发布通知时)收到这个通知。

//一个通知一般包含三个属性:
@property (readonly, copy) NSString *name;//通知名称
@property (nullable, readonly, retain) id object;//通知发布者(是谁要发布通知)
@property (nullable, readonly, copy) NSDictionary *userInfo;//一些额外的信息(通知发布者传递给通知接收者的信息内容)

 //初始化一个通知:(NSNotification)对象
 + (instancetype)notificationWithName:(NSString *)aName object:(nullable id)anObject;
 
 + (instancetype)notificationWithName:(NSString *)aName object:(nullable id)anObject userInfo:(nullable NSDictionary *)aUserInfo;
 
 //发布通知方法(通知中心提供了相应的方法来帮助发布通知)
    
  //1.发布一个notification通知,可在notification对象中设置通知的名称,通知发布者、额外的信息等
- (void)postNotification:(NSNotification *)notification;
    
//2.发布一个名称为aName的通知,anObject为这个通知的发布者
- (void)postNotificationName:(NSString *)aName object:(nullable id)anObject;
    
 //3.发布一个名称为aName的通知,anObject为这个通知的发布者,aUserInfo为额外信息(通知的内容)
- (void)postNotificationName:(NSString *)aName object:(nullable id)anObject userInfo:(nullable NSDictionary *)aUserInfo;

在这里举个例子,比如这里有新浪和腾讯新闻在发布新闻。张三喜欢收听娱乐新闻,李四喜欢收听搞笑新闻。当新浪和腾讯发出的新闻只要是娱乐新闻张三都能收听到,发出的新闻只要是搞笑新闻李四都能收听到,怎么实现呢,看如下代码:

//首先创建一个新闻发布类,有一个属性名字(比如新浪和腾讯)
#import <Foundation/Foundation.h>
@interface NewsCompany : NSObject
@property (nonatomic, copy) NSString *name;
@end

//再创建一个Person类(有一个name属性和接收到新闻后做出的回应)
@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
//接收到消息后触发的方法
- (void)newCome:(NSNotification *)note;
@end

//Person.m文件中实现接收到通知后的方法
#import "Person.h"
#import "NewsCompany.h"

@implementation Person

- (void)newCome:(NSNotification *)note{
    
    //取到通知发布者
    NewsCompany *obj = note.object;
    NSLog(@"%@接收到%@的通知,通知内容是:%@",self.name,obj.name, note.userInfo);
}

//通知中心不会保留(retain)监听器对象,在通知中心注册过的对象,必须在该对象释放前取消注册。否则,当相应的通知再次出现时,通知中心仍然会向该监听器发送消息。因为相应的监听器对象已经被释放了,所以可能会导致应用崩溃
- (void)dealloc {
    
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}


//然后我们在ViewController.m文件中实现他们

//首先创建两个新闻发布的对象(新浪和腾讯)
NewsCompany *company = [[NewsCompany alloc] init];
company.name = @"腾讯新闻";
    
NewsCompany *sian = [[NewsCompany alloc] init];
sian.name = @"新浪新闻";

//初始化两个人
 Person *zhansan = [[Person alloc] init];
 zhansan.name = @"张三"; 
  
 Person *lisi = [[Person alloc] init];
 lisi.name = @"李四";

 //模拟发布通知
 //初始化通知中心
 NSNotificationCenter *center = [NSNotificationCenter defaultCenter];

//注册通知监听器
    /**
     *  注册一个监听通知的监听器
     *
     *  @param observer  监听器,即谁要接收这个通知
     *  @param aSelector 收到通知后,回调监听器这个方法,并且把通知对象当做参数传入
     *  @param aName     通知的名称,如果为nil,那么无论通知名称是什么,监听器都能收到这个通知
     *  @param anObject  通知发布者(如果为nil,不关心是谁发布的通知,可以更具通知的名称来获得哪条通知,如果aName和anObject都为nil)
     */
// - (void)addObserver:(id)observer selector:(SEL)aSelector name:(nullable NSString *)aName object:(nullable id)anObject;

//注册一个张三要接收军事新闻的监听器,接收到消息后会调用- (void)newCome:(NSNotification *)note方法

[center addObserver:zhansan selector:@selector(newCome:) name:@"junshi_new_come" object:nil];

[center addObserver:lisi selector:@selector(newCome:) name:@"gaoxiao_new_come" object:nil];


//发布通知
//腾讯发布了一侧通知
[center postNotificationName:@"junshi_new_come" object:company userInfo:@{@"title":@"哈哈哈哈哈我的武器好厉害",@"intro":@"哈哈哈哈哈我的武器好厉害......"}];

//新浪发布了一条搞笑新闻
[center postNotificationName:@"gaoxiao_new_come" object:sian userInfo:@{@"title":@"哈哈哈太搞笑了"}];

//然后运行工程打印如下:
2016-09-12 22:08:07.552 通知的使用[1748:85334] 张三接收到腾讯新闻的通知,通知内容是:{
    intro = "\U4f0a\U62c9\U514b\U6218\U4e89\U505c\U6b62\U4e86......";
    title = "\U4f0a\U62c9\U514b\U6218\U4e89\U505c\U6b62\U4e86";
}
2016-09-12 22:08:07.552 通知的使用[1748:85334] 李四接收到新浪新闻的通知,通知内容是:{
    title = "\U54c8\U54c8\U54c8\U592a\U641e\U7b11\U4e86";
}

//证明张三和李四都接收到了各自喜爱的新闻

注意事项

  • 在通知中心注册过的对象,必须在该对象释放前取消注册。否则,当相应的通知再次出现时,通知中心仍然会向该监听器发送消息。因为相应的监听器对象已经被释放了,所以可能会导致应用崩溃
- (void)dealloc {

    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
  • 执行顺序:一定要先向通知中心注册通知监听器,也就是谁要监听谁发布的消息,然后再执行发布消息,不然会导致消息发出来了没人接收的情况

通知的使用方法二:

使用Block的方法监听通知:
- (id <NSObject>)addObserverForName:(nullableNSString *)name object:(nullableid)obj queue:(nullableNSOperationQueue *)queue usingBlock:(void (^)(NSNotification *note))block NS_AVAILABLE(10_6, 4_0);

@interface ViewController ()
@property (nonatomic, weak) id observe;
@end

- (void)test2 {//监听通知方式二:       
//1.监听通知
    /**
     *  监听通知
     *
     *  Name:通知名称
     object:谁发出的通知
     queue:队列(决定block在哪个线程中区执行,传入nil:在发布通知的线程中去执行,也就是发布通知在哪个线程,block就在哪个线程中区执行)
     usingBlock:监听到通知的block回调
     注意:一定要移除
     */

    _observe = [[NSNotificationCenter defaultCenter] addObserverForName:@"name" object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
        
        //只要监听到通知 就会调用
        NSLog(@"%@",[NSThread currentThread]);
        
        
    }];
    
    
    //2.发送通知
    /**
     *  Name:通知名字
     object:谁发出的通知
     */
    [[NSNotificationCenter defaultCenter] postNotificationName:@"note" object:nil];
    

    
}
//方式二:移除通知
- (void)dealloc {
        
    [[NSNotificationCenterdefaultCenter] removeObserver:_observe];
}

二、通知在异步线程中的使用

异步监听通知方法一:

- (void)test3{
   
     //方法一:异步监听通知
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reciveNote) name:@"note" object:nil];
    });
    
}

//防止先发送通知,后监听通知,导致接收不到通知,这里采用延迟发送通知(点击屏幕后再发送通知)
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    
    //2.发送通知
    /**
     *  Name:通知名字
     object:谁发出的通知
     */
    [[NSNotificationCenter defaultCenter] postNotificationName:@"note" object:nil];
}

/**
 *  监听到通知就会调用
    异步:监听通知 主线程:发出通知
 //总结:接收通知代码,由发布通知线程决定
 */
- (void)reciveNote {
    
    //注意点:如果是在异步发送通知,如果需要更新UI,为了安全起见,需要回到主线程更新UI
    dispatch_async(dispatch_get_main_queue(), ^{
        
        NSLog(@"%@",[NSThread currentThread]);
        //打印结果:2016-09-18 22:59:42.915 通知-多线程使用[1748:87249] <NSThread: 0x7fcff0c05b40>{number = 1, name = main}

    });
}

- (void)dealloc {
    
    //方式一:移除通知
  [[NSNotificationCenter defaultCenter] removeObserver:self];
异步监听通知方法二:
- (void)test4 {//异步通知方式二:      
 //1.监听通知
    
    //queue:[NSOperationQueue mainQueue]即使发送通知在异步,block也会在主线程中执行,所以为了安全起见queue:一般是使用主队列
    _observe = [[NSNotificationCenter defaultCenter] addObserverForName:@"note" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
        
        //只要监听到通知 就会调用
        NSLog(@"%@",[NSThread currentThread]);
        
    }];
    
    //2.发送通知
    /**
     *  Name:通知名字
     object:谁发出的通知
     */
    
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        
         [[NSNotificationCenter defaultCenter] postNotificationName:@"note" object:nil];
    });
}

- (void)dealloc {
    //方式二:移除通知
    [[NSNotificationCenter defaultCenter] removeObserver:_observe];
}

相关文章

网友评论

  • liusong007:写通知的 注册通知 接收通知最写在两个类里面,不怎么用通知看你这个很容易被带沟里:joy:
  • 小赢一场:我测试了下对象销毁后,再向对象发送通知,没有崩溃啊
  • KeepCuriosity:耗时操作在子线程,主线程执行block没毛病
  • nonooon:这异步,看不出来

本文标题:IOS 通知详解+异步发送和接收通知

本文链接:https://www.haomeiwen.com/subject/cgmvettx.html