`

(转)【iOS 】NSNotificationCenter 使用

    博客分类:
  • IOS
阅读更多

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

 

总结图:

 

 

 传值:通过object field

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

 

[center postNotificationName:@"tag" object:@"1"];

 

在被调用的方法,通过notification获得object 

-(void)wifisetupMove :(NSNotification*) notification
{
    
    NSString *type1 = [notification object];
    int type = [type1 intValue];
    if(type == 1){
       ...
    }

}

 

 

最近在做平板的过程中,发现了一些很不规范的代码。偶然修复支付bug的时候,看到其他项目代码,使用通知的地方没有移除,我以为我这个模块的支付闪退是因为他通知没有移除的缘故。而在debug和看了具体的代码的时候才发现和这里没有关系。在我印象中,曾经因为没有移除通知而遇到闪退的问题。所以让我很意外,于是写了个demo研究了下,同时来讲下NSNotificationCenter使用的正确姿势。

NSNotificationCenter

对于这个没必要多说,就是一个消息通知机制,类似广播。观察者只需要向消息中心注册感兴趣的东西,当有地方发出这个消息的时候,通知中心会发送给注册这个消息的对象。这样也起到了多个对象之间解耦的作用。苹果给我们封装了这个NSNotificationCenter,让我们可以很方便的进行通知的注册和移除。然而,有些人的姿势还是有点小问题的,下面就看看正确的姿势吧!

正确姿势之remove

只要往NSNotificationCenter注册了,就必须有remove的存在,这点是大家共识的。但是大家在使用的时候发现,在UIViewControlleraddObserver后没有移除,好像也没有挂!我想很多人可能和我有一样的疑问,是不是因为使用了ARC?在你对象销毁的时候自动置为nil了呢?或者苹果在实现这个类的时候用了什么神奇的方式呢?下面我们就一步步来探究下。

首先,向NSNotificationCenteraddObserver后,并没有对这个对象进行引用计数加1操作,所以它只是保存了地址。为了验证这个操作,我们来做下代码的测试。

一个测试类,用来注册通知:

@implementation MRCObject

- (id)init
{
    if (self = [super init]) {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(test) name:@"test" object:nil];
    }
    return self;
}

- (void)test
{
    NSLog(@"=================");
}

- (void)dealloc
{
    [super dealloc];
}

@end

这个类很简单,就是在初始化的时候,给他注册一个通知。但是在销毁的时候不进行remove操作。我们在VC中创建这个对象后,然后销毁,最后发送这个通知:

- (void)viewDidLoad {
    [super viewDidLoad];

    MRCObject *obj = [[MRCObject alloc] init];
    [obj release];

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

在进入这个vc后,我们发现挂了。。而打印出的信息是:

2015-01-19 22:49:06.655 测试[1158:286268] *** -[MRCObject test]: message sent to deallocated instance 0x17000e5b0

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

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

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

- (void)viewDidLoad {
    [super viewDidLoad];
    [[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]; 这个方法,因为你有可能移除了系统注册的通知

正确姿势之注意重复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那么当消息发生的时候,你的方法会被调用多次,这点必须牢记在心。

正确姿势之多线程通知

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

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 ([[NSThread currentThread] 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];
    });
}

总结

通知平常使用的知识点差不多就这么多。希望对大家有帮助。最后,代码一定要养成良好的习惯,该移除的还是要移除。

  • 大小: 75.4 KB
分享到:
评论

相关推荐

    ios NSNotificationCenter通知的简单使用

    iOS NSNotificationCenter 通知的简单使用 iOS NSNotificationCenter 通知是 iOS 开发中常用的技术之一,主要用于实现对象之间的通信和交互。在本文中,我们将详细介绍 NSNotificationCenter 通知的简单使用,包括...

    iOS NSNotificationCenter通知中心使用小结

    【iOS NSNotificationCenter通知中心使用小结】 iOS中的NSNotification中心是一个重要的通信机制,它允许对象间进行松耦合的消息传递。NSNotification与Delegate都是iOS中常见的消息传递方式,它们各有特点和适用...

    ios 消息NSNotificationCenter多页面传参

    标题"ios 消息NSNotificationCenter多页面传参"指的是使用`NSNotificationCenter`在不同页面之间传递参数,以便更新界面。 `NSNotificationCenter`是Foundation框架的一部分,它提供了一个观察者模式的实现,使得一...

    ios-对NSNotificationCenter的封装.zip

    这个`ios-对NSNotificationCenter的封装.zip`文件提供了一个针对NSNotification的封装,目的是简化使用过程,增强代码的可读性和可维护性。下面将详细解释封装的几个核心方面。 首先,`添加观察者`是NSNotification...

    NSNotificationCenter 的使用

    总之,`NSNotificationCenter`是iOS开发中不可或缺的一部分,它提供了一种灵活的方式来实现对象间的通信,但同时也需要谨慎使用,以避免不必要的复杂性和潜在的性能问题。正确地理解和运用这一工具,可以帮助我们...

    ios demo,NSNotificationCenter,app进入后台时的调用和就、进入前台时的调用

    本示例“ios demo,NSNotificationCenter,app进入后台时的调用和进入前台时的调用”是关于如何利用`NSNotificationCenter`来监听应用状态的变化,特别是当应用进入后台和返回前台时的事件处理。`...

    iOS基础——通知代理之NSNotificationCenter、Delegate

    在iOS开发中,通知代理是实现对象间通信的重要机制,主要分为两个方面:NSNotificationCenter和Delegate。这两种方式都允许一个对象监听并响应其他对象的事件,但它们各自有其特性和适用场景。 首先,我们来详细...

    AutoRemoveObserverDemo:自动删除NSNotificationCenter观察器的演示

    替换NSNotificationCenter的 addObserver... 方法, 新方法中用一个 Wrapper对象来封装传进来的Observer. 想通过真正的observer被释放时触发wrapper的 realObserver setter方法, 从而移除通知. //Wrapper.h @...

    iOS中使用 Reachability 检测网络

    这篇博客文章将深入探讨如何在iOS项目中使用Reachability来监控网络状态,并提供相关的源码分析。 一、 Reachability简介 Reachability是由Tony Million编写的开源库,后来被Apple纳入到其示例代码中,成为iOS...

    iOS基础——通知代理之NSNotificationCenter、Delegate(新)

    在iOS开发中,通知代理是实现对象间通信的重要机制,主要分为`NSNotificationCenter`和`Delegate`两种方式。本文将深入探讨这两种技术,并提供一个`DelegateDemo`实例来帮助理解。 首先,我们来看`NSNotification`...

    SFObservers, NSNotificationCenter和KVO自动删除观察者.zip

    SFObservers, NSNotificationCenter和KVO自动删除观察者 在任何项目中,我不再使用 SFObservers,但仍然会接受请求的请求。命令行目SFObservers是在NSNotificationCenter和KVO中为观察者 Pattern 添加自动删除的类别...

    网络连接 与 NSNotificationCenter

    标题 "网络连接 与 NSNotificationCenter" 涉及到的是iOS开发中的两个核心概念:网络状态监测和应用程序的通知中心机制。这篇博文可能讨论了如何利用苹果的 Reachability 框架来检测设备的网络状态,并结合 ...

    使用NSNotificationCenter的通知发布及监听DEMO

    在iOS开发中,NSNotificationCenter是Objective-C和Swift中用于对象间通信的重要机制。它提供了一种松耦合的方式,让对象可以在不直接引用彼此的情况下传递信息。本DEMO旨在通过实例来详细介绍如何使用...

    objective-C NSNotificationCenter (通知

    iOS 通知 转发

    izevent:NSNotificationCenter的纯替代品

    IZEvent IZEvent是NSNotificationCenter的纯Swift替代方案。 它努力做到简单,安全和简单。 Pro的NSNotificationCenter上: 内存安全:不会发生内存泄漏,也不需要在deinit中删除观察者线程安全:默认情况下将事件...

    [转]IOS开发-使用Storyboar…

    在iOS应用开发中,使用Storyboard是一种常见的界面设计和管理方式,它可以直观地构建用户界面,并通过连接不同的视图控制器(UIViewController)实现界面间的跳转。本文将深入探讨如何在Storyboard中进行界面跳转...

    ios-iOS 纯代码基础框架 包括各种分类干货.zip

    【iOS 纯代码基础框架】是iOS应用开发中的一个重要组成部分,主要涵盖了使用纯代码(非Storyboard或SwiftUI)构建应用程序的基本架构和技术。这个压缩包“ios-iOS 纯代码基础框架 包括各种分类干货.zip”包含了Ws...

    iOS各种的代码

    7. **通知(Notification)**:通过NSNotification和NSNotificationCenter,可以在应用程序的不同部分之间传递消息。包括本地通知和远程推送通知。 8. **动画**:利用CAAnimation和UIView的动画方法可以创建丰富的...

Global site tag (gtag.js) - Google Analytics