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環境中就用第一種書寫方式好了。

 

這些只是個人的理解與代碼測試,如果有更恰當的理解方式與說明,請留言告訴我。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM