zoukankan      html  css  js  c++  java
  • IOS中通知中心(NSNotificationCenter)

     

    IOS中通知中心NSNotificationCenter应用总结

    一、了解几个相关的类

    1、NSNotification

    这个类可以理解为一个消息对象,其中有三个成员变量。

    这个成员变量是这个消息对象的唯一标识,用于辨别消息对象。

    @property (readonly, copy) NSString *name;

    这个成员变量定义一个对象,可以理解为针对某一个对象的消息。

    @property (readonly, retain) id object;

    这个成员变量是一个字典,可以用其来进行传值。

    @property (readonly, copy) NSDictionary *userInfo;

    NSNotification的初始化方法:

    - (instancetype)initWithName:(NSString *)name object:(id)object userInfo:(NSDictionary *)userInfo;

    + (instancetype)notificationWithName:(NSString *)aName object:(id)anObject;

    + (instancetype)notificationWithName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo;

    注意:官方文档有明确的说明,不可以使用init进行初始化

    2、NSNotificationCenter

    这个类是一个通知中心,使用单例设计,每个应用程序都会有一个默认的通知中心。用于调度通知的发送的接受。

    添加一个观察者,可以为它指定一个方法,名字和对象。接受到通知时,执行方法。

    - (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject;

    发送通知消息的方法

    - (void)postNotification:(NSNotification *)notification;

    - (void)postNotificationName:(NSString *)aName object:(id)anObject;

    - (void)postNotificationName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo;

    移除观察者的方法

    - (void)removeObserver:(id)observer;

    - (void)removeObserver:(id)observer name:(NSString *)aName object:(id)anObject;

    几点注意:

    1、如果发送的通知指定了object对象,那么观察者接收的通知设置的object对象与其一样,才会接收到通知,但是接收通知如果将这个参数设置为了nil,则会接收一切通知。

    2、观察者的SEL函数指针可以有一个参数,参数就是发送的死奥西对象本身,可以通过这个参数取到消息对象的userInfo,实现传值。

    二、通知的使用流程

    首先,我们在需要接收通知的地方注册观察者,比如:

    1
    2
    3
    4
        //获取通知中心单例对象
        NSNotificationCenter * center = [NSNotificationCenter defaultCenter];
        //添加当前类对象为一个观察者,name和object设置为nil,表示接收一切通知
        [center addObserver:self selector:@selector(notice:) name:@"123" object:nil];

    之后,在我们需要时发送通知消息

    1
    2
    3
    4
        //创建一个消息对象
        NSNotification * notice = [NSNotification notificationWithName:@"123" object:nil userInfo:@{@"1":@"123"}];
        //发送消息
           [[NSNotificationCenter defaultCenter]postNotification:notice];

    我们可以在回调的函数中取到userInfo内容,如下:

    1
    2
    3
    -(void)notice:(id)sender{
        NSLog(@"%@",sender);
    }

    打印结果如下:

     

    iOS NSNotification的使用 

    分类: Objective-C
    如果在一个类中想要执行另一个类中的方法可以使用通知
    1.创建一个通知对象:使用notificationWithName:object: 或者 notificationWithName:object:userInfo:

        NSNotification* notification = [NSNotification notificationWithName:kImageNotificationLoadFailed(connection.imageURL)
                                                                     object:self
                                                                   userInfo:[NSDictionary dictionaryWithObjectsAndKeys:error,@"error",connection.imageURL,@"imageURL",nil]];

    这里需要注意的是,创建自己的通知并不是必须的。而是在创建自己的通知之前,采用NSNotificationCenter类的方法 postNotificationName:object: 和 postNotificationName:object:userInfo:更加便利的发出通知。这种情况,一般使用NSNotificationCenter的类方法defaultCenter就获得默认的通知对象,这样你就可以给该程序的默认通知中心发送通知了。注意:每一个程序都有一个自己的通知中心,即NSNotificationCenter对象。该对象采用单例设计模式,采用defaultCenter方法就可以获得唯一的NSNotificationCenter对象。

    注意:NSNotification对象是不可变的,因为一旦创建,对象是不能更改的。

    2.注册通知:addObserver:selector:name:object:

    可以看到除了添加观察者之外,还有其接收到通知之后的执行方法入口,即selector的实参。因此为了进行防御式编程,最好先检查观察者是否定义了该方法。例如:添加观察者代码有

    [[NSNotificationCenter defaultCenter] addObserver:self
        selector:@selector(aWindowBecameMain:)
        name:NSWindowDidBecomeMainNotification object:nil];

    这里保证了self定义了aWindowBecameMain:方法。而对于一个任意的观察者observer,不能保证其对应的selector有aWindowBecameMain:,可采用[observer respondsToSelector:@selector(aWindowBecameMain:)]] 进行检查。所以完整的添加观察者过程为:

    if([observer respondsToSelector:@selector(aWindowBecameMain:)]) {
            [[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(aWindowBecameMain:) name:NSWindowDidBecomeMainNotification object:nil];
        }

    注意到addObserver:selector:name:object:不仅指定一个观察者,指定通知中心发送给观察者的消息,还有接收通知的名字,以及指定的对象。一般来说不需要指定name和object,但如果仅仅指定了一个object,观察者将收到该对象的所有通知。例如将上面的代码中name改为nil,那么观察者将接收到object对象的所有消息,但是确定不了接收这些消息的顺序。如果指指定一个通知名称,观察者将收到它每次发出的通知。例如,上面的代码中object为nil,那么客户对象(self)将收到任何对象发出NSWindowDidBecomeMainNotification通知。如果既没有指定指定object,也没有指定name,那么该观察者将收到所有对象的所有消息。

    3.发送通知:postNotificationName:object:或者performSelectorOnMainThread:withObject:waitUntilDone:

    例如程序可以实现将一个文本可以进行一系列的转换,例如对于一个实例、RTF格式转换成ASCII格式。而转换在一个类(如Converter类)的对象中得到处理,在诚寻执行过程中可以加入或者删除这种转换。而且当添加或者删除Converter操作时,你的程序可能需要通知其他的对象,但是这些Converter对象并不需要知道被通知对象是什么,能干什么。你只需要声明两个通知,"ConverterAdded" 和 "ConverterRemoved",并且在某一事件发生时就发出这两个通知。

    当一个用户安装或者删除一个Converter,它将发送下面的消息给通知中心:

    [[NSNotificationCenter defaultCenter]
        postNotificationName:@"ConverterAdded" object:self];

    或者是

    [[NSNotificationCenter defaultCenter]
        postNotificationName:@"ConverterRemoved" object:self];

    通知中心将会区分它们对象对这些通知感兴趣并且通知他们。如果除了关心观察者的通知名称和观察的对象,还关心其他之外的对象,那么就把之外的对象放在通知的可选字典中,或者用方法postNotificationName:object:userInfo:。

    而采用performSelectorOnMainThread:withObject:waitUntilDone:则是直接调用NSNotification的方法postNotification,而postNotificationName和object参数可以放到withObject的实参中。例如:

    [[NSNotificationCenter defaultCenter] performSelectorOnMainThread:@selector(postNotification:) withObject:notification waitUntilDone:YES];//注意这里的notification为自定义的一个通知对象,可定义为NSNotification* notification = [NSNotification notificationWithName:@"ConverterAdded"object:self];//那么它的作用与上面的一致

    4.移除通知:removeObserver:和removeObserver:name:object:

    其中,removeObserver:是删除通知中心保存的调度表一个观察者的所有入口,而removeObserver:name:object:是删除匹配了通知中心保存的调度表中观察者的一个入口。

    这个比较简单,直接调用该方法就行。例如:

    [[NSNotificationCenter defaultCenter] removeObserver:observer name:nil object:self];

    注意参数notificationObserver为要删除的观察者,一定不能置为nil。

    PS:这里简单说一下通知中心保存的调度表。通知中心的调度表是给一些观察者指定的一些通知集。一个通知集是通知中心发出的通知的子集。每个表的入口包含:

    通知观察者(必须要的)、通知名称、通知的发送者。

    下图表示通知集中指定的通知的调用表入口的四种类型:

    下图表示四种观察者的调度表

    最后,提醒一下观察者收到通知的顺序是没有定义的。同时通知发出和观察的对象有可能是一样的。通知中心同步转发通知给观察者,就是说 postNotification: 方法直到接收并处理完通知才返回值。要想异步的发送通知,可以使用NSNotificationQueue。在多线程编程中,通知一般是在一个发出通知的那个线程中转发,但也可能是不在同一个线程中转发通知。

     
     
     
     
  • 相关阅读:
    Servant:基于Web的IIS管理工具
    mono-3.4.0 源码安装时出现的问题 [do-install] Error 2 [install-pcl-targets] Error 1 解决方法
    使用 OWIN Self-Host ASP.NET Web API 2
    Xamarin和微软发起.NET基金会
    SQLite vs MySQL vs PostgreSQL:关系型数据库比较
    Mono 3.2.7发布,JIT和GC进一步改进
    如何使用Microsoft技术栈
    c#开源消息队列中间件EQueue 教程
    通过一组RESTful API暴露CQRS系统功能
    NEsper Nuget包
  • 原文地址:https://www.cnblogs.com/fengmin/p/4971506.html
Copyright © 2011-2022 走看看