【IOS开发基础系列】Notification消息通知专题

1 NSNotificationCenter机制

1.1 原理

1.1.1 不移除通知挂机原因分析

@implementation MRCObject

- (id)init

{

    if (self = [superinit]) {

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(test) name:@"test"object:nil];

    }

    return self;

}


- (void)test

{

    NSLog(@"=================");

}


- (void)dealloc

{

    [super dealloc];

}


@end



在另一个类中引用:

- (void)viewDidLoad {

    [superview DidLoad];

    MRCObject *obj = [[MRCObjectalloc] init];

    [obj release];

    [[NSNotificationCenter defaultCenter] postNotificationName: @"test" object: nil];

}


    在进入这个vc后,我们发现挂了。。

    我们可以发现,向野指针对象发送了消息,所以挂掉了。从这点来看,苹果实现也基本差不多是这样的,只保存了个对象的地址,并没有在销毁的时候置为nil。

    这点就可以证明,addObserver后,必须要有remove操作。


1.1.2 ViewController中不手动移除通知不挂机原因分析

    现在我们在UIViewController中注册通知,不移除,看看会不会挂掉。

- (void)viewDidLoad {

    [superviewDidLoad];

    [[NSNotificationCenter defaultCenter] addObserver: self selector:@selector(test) name: @"test" object: nil];

}

    首先用navigationController进入到这个页面,然后pop出去。最后点击发送通知的按钮事件:

- (void)didButtonClicked:(id)sender

{

    [[NSNotificationCenter defaultCenter] postNotificationName: @"test" object: nil];

}

        无论你怎么点击这个按钮,他就是不挂!这下,是不是很郁闷了?我们可以找找看,你代码里面没有remove操作,但是NSNotificationCenter那边已经移除了,不然肯定会出现上面野指针的问题。看来看去,也只能说明是UIViewController自己销毁的时候帮我们暗地里移除了。

        那我们如何证明呢?由于我们看不到源码,所以也不知道有没有调用。这个时候,我们可以从这个通知中心下手!!!怎么下手呢?我只要证明UIViewController在销毁的时候调用了remove方法,就可以证明我们的猜想是对的了!这个时候,就需要用到我们强大的类别这个特性了。我们为NSNotificationCenter添加个类别,重写他的- (void)removeObserver:(id)observer方法:

- (void)removeObserver:(id)observer

{

    NSLog(@"====%@

    remove===", [observer class]);

}

        这样在我们VC中导入这个类别,然后pop出来,看看发生了什么!

2015-01-19 22:59:00.580 测试[1181:288728] ====TestViewController remove===

        怎么样?是不是可以证明系统的UIViewController在销毁的时候调用了这个方法。(不建议大家在开发的时候用类别的方式覆盖原有的方法,由于类别方法具有更高的优先权,所以有可能影响到其他地方。这里只是调试用)。

        以上也提醒我们,在你不是销毁的时候,千万不要直接调用[[NSNotificationCenter

defaultCenter] removeObserver: self]; 这个方法,因为你有可能移除了系统注册的通知


1.1.3 多线程通知

    首先看下苹果的官方说明:

        Regular notification centers deliver notifications on the thread in which the notification was posted. Distributed notification centers deliver notifications on the main thread. At times, you may require notifications to be delivered on a particular thread that is determined by you instead of the notification center. For example, if an object running in a background thread is listening for notifications from the user interface, such as a window closing, you would like to receive the notifications in the background thread instead of the main thread. In these cases, you must capture the notifications as they are delivered on the default thread and redirect them to the appropriate thread.

        意思很简单,NSNotificationCenter消息的接受线程是基于发送消息的线程的。也就是同步的,因此,有时候,你发送的消息可能不在主线程,而大家都知道操作UI必须在主线程,不然会出现不响应的情况。所以,在你收到消息通知的时候,注意选择你要执行的线程。下面看个示例代码

//接受消息通知的回调

- (void)test

{

    if ([[NSThreadcurrentThread] isMainThread]) {

        NSLog(@"main");

    }else{

        NSLog(@"not main");

    }

    dispatch_async(dispatch_get_main_queue(), ^{

        //do your UI

    });

}


//发送消息的线程

- (void)sendNotification

{

    dispatch_queue_t defaultQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_async(defaultQueue, ^{

        [[NSNotificationCenter defaultCenter] postNotificationName: @"test" object: nil];

    });

}


2 开发技巧

2.1 常用开发技巧

2.1.1 注意重复addObserver

    在我们开发中,我们经常可以看到这样的代码:

- (void)viewWillAppear:(BOOL)animated

{

    [super viewWillAppear: animated];

    [[NSNotificationCenter defaultCenter] addObserver: self selector:@selector(test) name: @"test"  object: nil];

}


- (void)viewWillDisappear:(BOOL)animated

{

    [super viewWillDisappear :animated];

    [[NSNotificationCenter defaultCenter] removeObserver: self name:@"test" object: nil];

}

        就是在页面出现的时候注册通知,页面消失时移除通知。你这边可要注意了,一定要成双成对出现,如果你只在viewWillAppear 中 addObserver没有在viewWillDisappear 中 removeObserver那么当消息发生的时候,你的方法会被调用多次,这点必须牢记在心。


3 参考链接

iOS NSNotificationCenter使用姿势详解

http://www.jianshu.com/p/a4d519e4e0d5

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容