• NSNotificationCenter使用block方式的一点注意事项


    arc环境中

    1。可以正常dealloc释放

    id observer;
    
    -(void)back
    {
        [[NSNotificationCenter defaultCenter] removeObserver:observer];
        [self.navigationController popViewControllerAnimated:YES];
    }
    
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        observer = [[NSNotificationCenter defaultCenter] addObserverForName:kPopNotice object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification* note){
            [self back];
        }];
    }

     

    2.这样也可以正常释放

    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        __block OtherViewController* ovc = self;
    
        observer = [[NSNotificationCenter defaultCenter] addObserverForName:kPopNotice object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification* note){
    
    // 直接用self就不可以
    
            [ovc.navigationController popViewControllerAnimated:YES];
    
        }];
    }
    
     
    
    -(void)dealloc
    {
        [[NSNotificationCenter defaultCenter] removeObserver:observer];
        [super dealloc];
    }
    

    如果在dealloc的时候不removeObserver:observer,那么[NSNotificationCenter defaultCenter]仍然会保留这个observer,当再次post这个kPopNotice消息时,会继续调用block里面的方法,从而出错。而且[[NSNotificationCenter defaultCenter] removeObserver:self];也不会清除掉block方式注册的方法。

     

    1与2的区别在于,1是主动的removeObserver,2是在dealloc中才removeObserver。2中需要能正确的进去dealloc,那么就不能在block中使用self本身。

     

    3. 这样做无所谓,一样释放

    self.array = [[NSArray arrayWithObjects:@"1",@"2",@"3",@"4",@"5",@"6", nil] retain];
    
        [array enumerateObjectsUsingBlock:^(id obj,NSUInteger idx,BOOL *stop)
    
        {
    
            self.title = (NSString*)obj; 
    
            if (idx == 3) {
    
                *stop = YES;
    
            }
    
        }];

    虽然array明显没有释放,但是最后还是调用了dealloc,成功释放。

     

    综上,在非arc环境下,如果是[NSNotificationCenter defaultCenter]的block里面使用self,一定要用__block SELFTYPE* tmp = self;然后在block里面用tmp代替self,并且要在最后移除这个observer(而不是self)才算是安全的使用方法。

     

    那么arc的环境中呢?

    1.一种比较简单的写法

    __weak OtherViewController* ovc = self;
    
        ovc = self;
    
        
    
        observer = [[NSNotificationCenter defaultCenter] addObserverForName:kPopNotice object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification* note){
    
            [ovc.navigationController popViewControllerAnimated:YES];
    
        }];

    即使dealloc中不removeObserver也没有关系,反正ovc已经只想nil了(weak修饰)

    2.如果上面的block中的ova换成self,那么将导致retain cycle

    3.如果1中的block中的函数换成 [self  back],那么,那么,会出现这样的情况

    每次退出(pop)的时候没有dealloc,但是再次进入这个页面(push,当然是重新生成的一个),会调用dealloc,奇了个怪的。[ovc back]很正常。

    综上,在arc环境中就用第一种书写方式好了。

     

    这些只是个人的理解与代码测试,如果有更恰当的理解方式与说明,请留言告诉我。

  • 相关阅读:
    基于jQuery的上下无缝滚动应用(单行或多行)
    表单验证
    中国剩余定理 ( 的学习 )
    扩展欧几里德算法--学习笔记
    Vijos P1794 文化之旅
    1336 : Matrix Sum (hihocoder)
    nyoj 1030 hihocoder 1338
    多重邻接表
    图的存储 ( 十字链表 )
    01背包的变形
  • 原文地址:https://www.cnblogs.com/v2m_/p/2534987.html
Copyright © 2020-2023  润新知