zoukankan      html  css  js  c++  java
  • NSNotificationCenter基础知识

    Notification的工作机制

    1.对应用程序中其他地方发生的事件(比如增加一条数据库记录)感兴趣的对象,会向通告中心(Notification Center,NSNotificationCenter类的实例)注册,从而成为该事件的监听者。在注册过程中,监听者需要指定方法供通告中心在事件发生时调用。

    2.给数据库添加记录(或者类似事件)的对象给通告中心发一个通告(NSnotification的实例)。该通告对象包括识别通告的标志、发布通告的对象ID和可选的附加信息字典。

    3.通告中心发送消息到每个已注册的监听者,调用监听者指定的方法会将通告传给这些监听者。

    NSNotification对象

    NSNotification包含三个属性:

    name一个notification对象的name,由我们自己定义

    objectpost该notification的object,也就是sender

    userInfo伴随notification传递过去的数据,是一个NSDictionary

    NSNotificationCenter中的方法

    Getting the Notification Center

    + defaultCenter该方法用于获取当前程序中的center object

    Managing Notification Observers

    – addObserverForName:object:queue:usingBlock:

    对快代码的操作,详见:http://blog.sina.com.cn/s/blog_63ced45101016cih.html

    – addObserver:selector:name:object:

    notificationObserver 一个对象,作为observer,不能为空。

    notificationSelectorobserver接收到notificaiton后会调用的方法,该方法只能有一个参数,类似:- (void) mytest:(NSNotification*) notification

    notificationNamenotification的name,center只会像该observer发送指定name的notification

    notificationSender一个对象,作为sender,也就是说指定了只有改sender发送了name为上一个参数指定的notification,center才会向observer发送notification

    – removeObserver:

    notificationObserver 从center中删除observer,add方法调用后,要在合适的地方调用remove方法删除observer,否则如果多系调用add后,一个post会接收到多次notification

    – removeObserver:name:object:

    该方法与–addObserver:selector:name:object:结合起来使用

    Posting Notifications

    – postNotification:

        NSNotification

    – postNotificationName:object:

    notificationNamenotification name

    notificationSender发送notification的object

    – postNotificationName:object:userInfo:

    notificationNamenotification name

    notificationSender发送notification的object

    userInfo伴随着notification发送过去的数据,是一个NSDictionary

    Android中的四大组件之一Broadcast用来在手机上发送广播,无论是同一个程序中或是在其他的应用中,只要你注册接收该条广播,那么当广播发送之后,你就会收到,这种机制可以降低程序中间的耦合性,可以通过发送广播调用其他类中的东西。

    在IOS中也有类似Broadcast的机制,其中包括NSNotificationCenter和NSDistributedNotificationCenter机制。

    NSNotificationCenter。在IOS运行的每一个程序都有一个default center,不要自己创建。通过方法[NSNotificationCenter defaultCenter]可以获取center对象,center实际上是notification的dispatch table(调度表),center控制着程序中所有notification的添加、删除以及post后的响应。可以说NSNotificationCenter 是专门供一个程序中的不同类间的消息通信而设置的。

    NSDistributedNotificationCenter用于在不同程序之间post和receive notification,这个跟Android的Broadcast比较相似。

       

    Rank: 9Rank: 9Rank: 9

    威望
    0 点
    义气
    0 点
    楼主
     
     发表于 2013-5-25 21:19:08 |只看该作者
     
    1. 定义一个方法

    1. -(void) update{ } 
    复制代码

    2. 对象注册,并关连消息

    1. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(update) name:@"update" object:nil] 
    复制代码

    3. 在要发出通知消息的地方

    1. [[NSNotificationCenter defaultCenter] postNotificationName:@"update" object:nil];
    复制代码

    具体如何使用 Notifications

    http://blog.sina.com.cn/s/blog_5df7dcaf0100c0q2.html

    第十四章: 使用 Notifications

    用户可能使用RaiseMan并打开了几个document, 然后他发现紫色的背景颜色实在是不利于阅读文档正文. 于是,他打开Preferences panel修改背景颜色,不过令人失望的是,已经存在的文档的背景颜色不会跟着改变. 于是,这个用户可能会写信给你告诉你这些. 你也许会回复:"defualts会在document创建的时候才读取,保存document在打开"实际上,用户想说明的是他希望程序能立马刷新已经打开的文档. 如果这样,那该怎么做呢?我们需要把所有打开的document用一个list记录起来么?

    --- 什么是Notification? ---

    这个要求其实也很容易实现. 每个运行中的application都有一个NSNotificationCenter的成员变量,它的功能就类似公共栏. 对象注册关注某个确定的notification(如果有人捡到一只小狗,就去告诉我). 我们把这些注册对象叫做 observer. 其它的一些对象会给center发送notifications(我捡到了一只小狗). center将该notifications转发给所有注册对该notification感兴趣的对象. 我们把这些发送notification的对象叫做 poster

    很多的标准Cocoa类会发送notifications: 在改变size的时候,Window会发送notification; 选择table view中的一行时,table view会发送notification;我们可以在在线帮助文档中查看到标准cocoa对象发送的notification

    在我们的例子中,我们将MyDocumet对象注册为observer. 而preference controller在用户改变color时将发送notification. MyDocument在接受到该notification后改变background color

    在MyDocument对象释放前,我们必须从notification center移除我们注册的observer. 一般我们在dealloc方法中做这件事

    -- Notifications 不是什么 --


    当程序员们听到notification center的时候, 他们可能会联想到IPC(进程间通讯).他们认为:"我在一个程序中创建一个observer,然后在另外一个程序中发送一个notification". 这个设计没有办法工作的, notification center允许同一个程序中的不同对象通许,它不能跨越不同的程序 [Notification 就是设计模 式中的 观察者模式, cocoa为我们实现了该模式, 就像Java也有同样的实现一样]

    -- NSNotification 和 NSNotificationCenter

    Notification对象非常简单. 它就是poster要提供给observer的信息包裹. notification对象有两个重要的成员变量: name 和 object. 一般object都是指向poster(为了让observer在接受到notification时可以回调到poster)

    所以,notification有两个方法

    1. - (NSString *)name
    2. - (id)object
    复制代码

    NSNotificaitonCernter是架构的大脑了.它允许我们注册observer对象, 发送notification, 撤销observer对象注册

    下面是它的一些常用方法


    1. + (NSNotificationCenter *)defaultCenter
    复制代码

    返回notification center [类方法,返回全局对象, 单件模式.cocoa的很多的全局对象都是通过类似方法实现]

    1. - (void)addObserver:(id)anObserver
    2. selector:(SEL)aSelector
    3. name:(NSString *)notificationName
    4. object:(id)anObject
    复制代码

    注册anObserver对象:接受名字为notificationName, 发送者为anObject的notification. 当anObject发送名字为notificationName的notification时, 将会调用anObserver的aSelector方法,参数为该notification 

    . 如果notificationName为nil. 那么notification center将anObject发送的所有notification转发给observer

    . 如果anObject为nil.那么notification center将所有名字为notificationName的notification转发给observer

    1. - (void)postNotification:(NSNotification *)notification
    复制代码

    发送notification至notification center 

    1. - (void)postNotificationName:(NSString *)aName
    2. object:(id)anObject
    复制代码

    创建并发送一个notification

    1. - (void)removeObserver:(id)observer
    复制代码

    移除observer

    -- 发送一个Notification --

    发送notification是其中最简单的步骤了,所以我们从它开始实现.当我们接收到changeBackgroundColor:消息时, PreferenceController对象发送一个notification.

    我们将notification命名为@"BNRColorChanged" ,我们使用一个全局常量来指定.(有经验的程序员会使用一个前缀,这样避免和其他组件定义的notification混淆)打开PreferenceController.h 添加下面的的外部申明


    1. extern NSString * const BNRColorChangedNotification;
    复制代码

    在PreferenceController.m中定义常量

    1. NSString * const BNRColorChangedNotification = @"BNRColorChanged";
    复制代码

    在PreferenceController.m修改changeBackgroundColor:方法

    1. - (IBAction)changeBackgroundColor:(id)sender
    2. {
    3. NSColor *color = [colorWell color];
    4. NSData *colorAsData =
    5. [NSKeyedArchiver archivedDataWithRootObject:color];
    6. [[NSUserDefaults standardUserDefaults] setObject:colorAsData
    7. forKey:BNRTableBgColorKey];
    8. NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    9. NSLog(@"Sending notification");
    10. [nc postNotificationName:BNRColorChangedNotification object:self];
    11. }
    复制代码

    -- 注册成为Observer --

    要注册一个observer, 我们必须提供几个要数: 要成为observer的对象;所感兴趣的notification的名字;当notification发送时要调用的方法. 我们也可以指定要关注莫个对象的notification.(比如说,我们需要关注莫个特定的window的resize的notification)

    编辑MyDocument类的init方法

    1. - (id)init
    2. {
    3. if (![super init])
    4. return nil;
    5. employees = [[NSMutableArray alloc] init];
    6. NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    7. [nc addObserver:self
    8. selector:@selector(handleColorChange:)
    9. name:BNRColorChangedNotification
    10. object:nil];
    11. NSLog(@"Registered with notification center");
    12. return self;
    13. }
    复制代码

    同时在dealloc方法,将MyDocument从notification center中移除

    1. - (void)dealloc
    2. {
    3. [self setEmployees:nil];
    4. NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    5. [nc removeObserver:self];
    6. [super dealloc];
    7. }
    复制代码

    -- 处理Notification --

    当一个notification发生时, handleColorChange:方法将被调用. 目前我们在方法中简单的打印一些log.

    1. - (void)handleColorChange:(NSNotification *)note
    2. {
    3. NSLog(@"Received notification: %@", note);
    4. }
    复制代码

    编译运行程序,看到了我们想要的log了吧

    -- userInfo Dictionary --

    notification对象的object变量是poster,如果我们想要notification对象传递更多的信息,我们可以使用user info dictionary. 每个notification对象有一个变量叫 userInfo, 它是一个NSDictionary对象,用来存放用户希望随着notification一起传递到observer的其它信息. MyDocument将使用它来得到要改变的color.在PreferenceController.m添加userInfo


    1. - (IBAction)changeBackgroundColor:(id)sender
    2. {
    3. NSColor *color = [sender color];
    4. NSData *colorAsData;
    5. colorAsData = [NSKeyedArchiver archivedDataWithRootObject:color];
    6. [[NSUserDefaults standardUserDefaults] setObject:colorAsData
    7. forKey:BNRTableBgColorKey];
    8. NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    9. NSLog(@"Sending notification");
    10. NSDictionary *d = [NSDictionary dictionaryWithObject:color
    11. forKey:@"color"];
    12. [nc postNotificationName:BNRColorChangedNotification
    13. object:self
    14. userInfo:d];
    15. }
    复制代码

    在MyDocument.m,从userInfo中读取到color

    1. - (void)handleColorChange:(NSNotification *)note
    2. {
    3. NSLog(@"Received notification: %@", note);
    4. NSColor *color = [[note userInfo] objectForKey:@"color"];
    5. [tableView setBackgroundColor:color];
    6. }
    复制代码

    打开几个窗口,并改变背景颜色,现在,那些打开的窗口的背景颜色立马就变了.

    -- 思考 --

    通常当你将自己的一个对象设置为cocoa某个标准对象的delegate的时候,你同时或许也对该标准对象的notification感兴趣. 例如,我们实现一个window的delegate来处理 windowShouldClose: , 我们也许会对 NSWindowDidResizeNotification这样的notification感兴趣.

    如果一个cocoa标准对象有一个delegate,同时它也发送notification的话, cocoa对象会自动将它的delegate对象注册成为observer来接受接受自己的notification. 如果我们实现了一个delegate,那么delegate[也就是我们的对象]要怎样声明来接受notification呢?[方法的名字是什么?]

    方法名字其实很简单: 以notification名字为基准, 先将NS前缀去掉,接着将第一个字母改为小写. 在将后面的Notification去掉,然后加个冒号:. 例如,为了能接受到window的NSWindowDidResizeNotification, delegate可以实现方法:


    1. - (void)windowDidResize:(NSNotification *)aNotification
    复制代码

    当window改变大小时,这个方法将自动调用. 对于NSWindow,我们可以在.h或是帮助文档中找到类似的notification 来实现notification方法.

    -- 挑战 --

    当程序不再是active状态是,让程序发出beep. 当unactive时,NSApplication会发送NSApplicationDidResignActiveNotification的notificaiton. 而我们的AppController是NSApplication的delegate. 函数NSBeep()可以用来发出beep声音
  • 相关阅读:
    Codeforces 1255B Fridge Lockers
    Codeforces 1255A Changing Volume
    Codeforces 1255A Changing Volume
    leetcode 112. 路径总和
    leetcode 129. 求根到叶子节点数字之和
    leetcode 404. 左叶子之和
    leetcode 104. 二叉树的最大深度
    leetcode 235. 二叉搜索树的最近公共祖先
    450. Delete Node in a BST
    树的c++实现--建立一棵树
  • 原文地址:https://www.cnblogs.com/iOS-mt/p/4196527.html
Copyright © 2011-2022 走看看