zoukankan      html  css  js  c++  java
  • iOS 设计模式-NSNotificationCenter 通知中心

    通知介绍

    每一个应用程序都有一个通知中心(NSNotificationCenter)实例,专门负责协助不同对象之间的消息通信
    任何一个对象都可以向通知中心发布通知(NSNotification),描述自己在做什么。
    其他感兴趣的对象(Observer)可以申请在某个特定通知发布时(或在某个特定的对象发布通知时)收到这个通知

    初始化通知中心

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

    注册通知监听器

    通知中心(NSNotificationCenter)提供了方法来注册一个监听通知的监听器(Observer)

    方法一:

    - (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject;
    • observer:监听器,即谁要接收这个通知
    • aSelector:收到通知后,回调监听器的这个方法,并且把通知对象当做参数传入
    • aName:通知的名称。如果为nil,那么无论通知的名称是什么,监听器都能收到这个通知
    • anObject:通知发布者。如果为anObject和aName都为nil,监听器都收到所有的通知

    方法二:

    - (id)addObserverForName:(NSString *)name object:(id)obj queue:(NSOperationQueue *)queue 
                   usingBlock:(void (^)(NSNotification *note))block;
    • name:通知的名称
    • obj:通知发布者
    • block:收到对应的通知时,会回调这个block
    • queue:决定了block在哪个操作队列中执行,如果传nil,默认在当前操作队列中同步执行

    发布通知

    通知中心(NSNotificationCenter)提供了相应的方法来帮助发布通知

    - (void)postNotification:(NSNotification *)notification;
    发布一个notification通知,可在notification对象中设置通知的名称、通知发布者、额外信息等
     
    - (void)postNotificationName:(NSString *)aName object:(id)anObject;
    发布一个名称为aName的通知,anObject为这个通知的发布者
     
    - (void)postNotificationName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo;
    发布一个名称为aName的通知,anObject为这个通知的发布者,aUserInfo为额外信息

    取消注册通知监听器

    通知中心不会保留(retain)监听器对象,在通知中心注册过的对象,必须在该对象释放前取消注册。否则,当相应的通知再次出现时,通知中心仍然会向该监听器发送消息。因为相应的监听器对象已经被释放了,所以可能会导致应用崩溃
    •通知中心提供了相应的方法来取消注册监听器
    - (void)removeObserver:(id)observer;
    - (void)removeObserver:(id)observer name:(NSString *)aName object:(id)anObject;
    一般在监听器销毁之前取消注册(如在监听器中加入下列代码):
    - (void)dealloc {
      //[super dealloc];  非ARC中需要调用此句
        [[NSNotificationCenter defaultCenter] removeObserver:self];
    }

    实例代码

    两个新闻机构(腾讯新闻、新浪新闻),每当发布新闻时,通知订阅了该新闻的用户。

    新闻机构类 NewsCompany.h

    //  新闻发布机构
    
    #import <Foundation/Foundation.h>
    
    @interface NewsCompany : NSObject
    /**
     *  机构名称
     */
    @property (nonatomic, copy) NSString *name;
    @end

    NewsCompany.m

    #import "NewsCompany.h"
    
    @implementation NewsCompany
    
    @end

    订阅者类

    Person.h

    #import <Foundation/Foundation.h>
    
    @interface Person : NSObject
    /**
     * 姓名
     */
    @property (nonatomic, copy) NSString *name;
    
    - (void)newsCome:(NSNotification *)note;
    @end

    Person.m

    #import "Person.h"
    #import "NewsCompany.h"
    
    @implementation Person
    
    // 收到通知后,回调监听器的这个方法,并且把通知对象当做参数传入
    - (void)newsCome:(NSNotification *)note
    {
        // 通知的发布者
        NewsCompany *obj = note.object;
        
        NSLog(@"%@接收到了%@发出的通知,通知内容是:%@", self.name, obj.name, note.userInfo);
    }
    
    // 一般在监听器销毁之前取消注册
    - (void)dealloc
    {
    //    [super dealloc];
        [[NSNotificationCenter defaultCenter] removeObserver:self];
    }
    @end

    通知中心

    main.m

    #import <Foundation/Foundation.h>
    #import "Person.h"
    #import "NewsCompany.h"
    
    int main(int argc, const char * argv[])
    {
        @autoreleasepool {
            // 1.初始化机构
            NewsCompany *tx = [[NewsCompany alloc] init];
            tx.name = @"腾讯新闻";
            
            NewsCompany *sina = [[NewsCompany alloc] init];
            sina.name = @"新浪新闻";
            
            // 2.初始化2个人
            Person *zhangsan = [[Person alloc] init];
            zhangsan.name = @"张三";
            
            Person *lisi = [[Person alloc] init];
            lisi.name = @"李四";
            
            // 初始化通知中心
            NSNotificationCenter *center =[NSNotificationCenter defaultCenter];
            
            // 3.注册通知监听器
            // zhangsan只监听tx发出的junshi_news_come通知
            [center addObserver:zhangsan selector:@selector(newsCome:) name:@"junshi_news_come" object:nil];
            // lisi监听tx发的所有通知
            [center addObserver:lisi selector:@selector(newsCome:) name:nil object:tx];
            
            // 4.发布通知
            // tx发布了一则叫做junshi_news_come的通知
            [center postNotificationName:@"junshi_news_come"
                                  object:tx
                                userInfo:@{@"title" : @"伊拉克战争停止了",
                                           @"intro" : @"伊拉克战争停止了.........."}];
            
            // sina发布了一则叫做junshi_news_come的通知
            [center postNotificationName:@"yule_news_come"
                                  object:sina
                                userInfo:@{@"title" : @"6456456456456",
                                           @"intro" : @"7657567567567"}];
            
        }
        return 0;
    }

    运行结果:

    其它通知

    UIDevice设备通知

    UIDevice类提供了一个单粒对象,它代表着设备,通过它可以获得一些设备相关的信息,比如电池电量值(batteryLevel)、电池状态(batteryState)、设备的类型(model,比如iPod、iPhone等)、设备的系统(systemVersion)
    通过[UIDevice currentDevice]可以获取这个单粒对象
    UIDevice对象会不间断地发布一些通知,下列是UIDevice对象所发布通知的名称常量:
    • UIDeviceOrientationDidChangeNotification // 设备旋转
    • UIDeviceBatteryStateDidChangeNotification // 电池状态改变
    • UIDeviceBatteryLevelDidChangeNotification // 电池电量改变
    • UIDeviceProximityStateDidChangeNotification // 近距离传感器(比如设备贴近了使用者的脸部)

    键盘通知

    系统发出键盘通知时,会附带一下跟键盘有关的额外信息(字典),字典常见的key如下:
    • UIKeyboardFrameBeginUserInfoKey // 键盘刚开始的frame
    • UIKeyboardFrameEndUserInfoKey // 键盘最终的frame(动画执行完毕后)
    • UIKeyboardAnimationDurationUserInfoKey // 键盘动画的时间
    • UIKeyboardAnimationCurveUserInfoKey // 键盘动画的执行节奏(快慢)

    使用方式

    监听:

        // 2.监听键盘的通知
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];

    取消监听:

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

    最后 

    在使用过程中,我们需要注意,最后通知的线程,是由发起通知的线程决定的。如果发起通知是主线程,则收到的通知也是主线程。

    更新UI必须要在主线程中更新,因此,我们最好在所有的通知回调中,都判断一下,如果当前线程不是主线程,则回到主线程。

    宏定义如下,这个在SDWebImage里有这个宏定义。

    #define dispatch_main_async_safe(block)
        if ([NSThread isMainThread]) {
            block();
        } else {
            dispatch_async(dispatch_get_main_queue(), block);
        }
  • 相关阅读:
    670. Maximum Swap
    653. Two Sum IV
    639. Decode Ways II
    636. Exclusive Time of Functions
    621. Task Scheduler
    572. Subtree of Another Tree
    554. Brick Wall
    543. Diameter of Binary Tree
    535. Encode and Decode TinyURL
    博客园自定义背景图片
  • 原文地址:https://www.cnblogs.com/jys509/p/4821253.html
Copyright © 2011-2022 走看看