2014-08-27 53 views
1

這裏有一個代碼片斷說明了這個問題爲什麼block對象不像NSObject那樣以dealloc的方式釋放?

__weak id ptr = nil; 
__weak id ptr2 = nil; 
@autoreleasepool { 
    void (^block)(void) = [^{ 
     NSLog(@"hahaha"); 
    } copy]; 
    block(); 
    [[(id)block rac_willDeallocSignal] subscribeCompleted:^{ 
     NSLog(@"block will dealloc"); 
    }]; 
    ptr = block; 
    int blockRetainCount = CFGetRetainCount((__bridge CFTypeRef)block); 

    NSObject *obj = [[NSObject alloc] init]; 
    [obj.rac_willDeallocSignal subscribeCompleted:^{ 
     NSLog(@"Obj dealloc"); 
    }]; 
    ptr2 = obj; 
    int objRetainCount = CFGetRetainCount((__bridge CFTypeRef)obj); 
    NSLog(@"oK"); 
} 
NSLog(@"after pool %@ %@" , ptr, ptr2); 

當我運行這個片段,我會看到Obj dealloc打印到控制檯,但不block will dealloc。在autorelease池之後,我也會看到ptr仍然包含一個有效的區塊,而ptr2已被正確重置爲零。爲什麼會有這種差異?塊什麼時候完全釋放?

回答

3

應該說服你多問題沒有嘗試過這樣的事情:

一,CFGetRetainCount不能保證在ARC的情況下返回任何有意義的東西。

二,不能保證一個塊根本不使用保留計數。不捕獲任何變量的塊被分配爲靜態變量;複製,保留等對他們什麼也不做,而且他們也不會被分配或釋放。

第三,不保證任何塊在解除分配時都會調用dealloc。並不保證它會在下一個操作系統或iOS版本中發生。

+0

我認爲我的關鍵詞是'不捕獲任何變量的塊被分配爲靜態變量;複製,保留等對他們不做任何事情,而且他們從未分配或釋放。「要測試一下。 – Tony 2014-08-27 19:28:00

+0

確實!如果我將塊定義改爲''' NSString * mystr = @「hahaha」; (void)(void)(void)= [^ {NS {} {@ @%@「,mystr); } copy]; '''那麼在自動釋放池的末尾,'ptr'被設置爲'nil'。 'CFGetRetainCount'和'dealloc'鉤子只是絕望的嘗試去理解爲什麼塊沒有被釋放:) – Tony 2014-08-27 19:31:07

+0

'CFGetRetainCount()'不保證返回任何有意義的東西。 – bbum 2014-12-20 17:24:00

相關問題