2012-04-23 40 views
5

我想使用__block變量來獲取塊中的值。但是,如果塊外,__block變量似乎是零。爲什麼會發生?「__block」變量在跳出塊時導致零值

NSString *fileName = [Tools MD5Encode:url]; 
    __block NSString *filePath = nil; 
    [fileList enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 
     NSString *aFileName = obj; 
     if ([aFileName isEqualToString:fileName]) { 
      NSString *path = [VERSIONS_INFO_DATA_DIRECTORY stringByAppendingPathComponent:aFileName]; 
      filePath = path; 
      NSLog(@"filePath1 %@", filePath); 
      *stop = YES; 
     } 
    }]; 
    //NSLog(@"filePath2 %@", filePath); 
    //filePath seems to be nil 
    return filePath; 

當我將代碼更改爲[路徑複製]時,它工作。但我不知道這是否是一個好主意。任何決定?

NSString *fileName = [Tools MD5Encode:url]; 
    __block NSString *filePath = nil; 
    [fileList enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 
     NSString *aFileName = obj; 
     if ([aFileName isEqualToString:fileName]) { 
      NSString *path = [VERSIONS_INFO_DATA_DIRECTORY stringByAppendingPathComponent:aFileName]; 
      filePath = [path copy]; 
      NSLog(@"filePath1 %@", filePath); 
      *stop = YES; 
     } 
    }]; 
    //NSLog(@"filePath2 %@", filePath); 
    return [filePath autorelease]; 
+1

這樣的情況讓我很高興我的團隊決定接受ARC。 – 2012-04-23 03:47:57

回答

1

這是確定這裏使用複製或保留的路徑上。您的問題的原因是NSString對象是便捷對象的成員,以及其他像NSArray的成員,您實際上不必發佈它們,並且在ARC時代之前已經由系統自動發佈。就我個人而言,我不喜歡他們這樣做,只是造成這樣的混亂。因爲塊完成執行系統autoreleases你分配的字符串對象導致泄漏。

5

http://www.mikeash.com/pyblog/friday-qa-2011-09-30-automatic-reference-counting.html

具體來說:

沒有ARC,__block還具有當它是由一個塊捕獲的不保留它的內容的副作用。塊會自動保留並釋放它們捕獲的任何對象指針,但是__block指針是特殊的,並且作爲弱指針。通過使用__block來避免保留週期,依賴此行爲已成爲常見模式。

在ARC下,__block現在保留其內容,就像其他捕獲的對象指針一樣。使用__block來避免保留週期的代碼將不再適用。相反,如上所述使用__weak。

所以你需要複製。

+0

我不相信「NSString * path = [VERSIONS_INFO_DATA_DIRECTORY stringByAppendingPathComponent:aFileName]是堆棧分配的對象」是正確的。據我所知,只有塊對象本身(不是由塊內代碼創建的任何對象)是一個堆棧對象。 http://www.friday.com/bbum/2009/08/29/blocks-tips-tricks/ – 2012-04-23 05:44:16

+0

你是對的...感謝糾正我。我將編輯我的帖子。 – 2012-04-23 12:48:51

1

在這裏使用塊甚至是個問題嗎?

在我看來,這個代碼序列:

NSString *filePath = nil; 
NSString *path = [VERSIONS_INFO_DATA_DIRECTORY stringByAppendingPathComponent:aFileName]; 
filePath = path; 
return [filePath autorelease]; 

過度釋放filePath(因爲你沒有自己的-stringByAppendingPathComponent:的結果,你不應該(自動)釋放它)

+0

好吧,我複製了錯誤的代碼。當我使用「filePath = path」時,應該返回filePath。然後,問題出現了。我現在糾正了它。 – Wayne 2012-04-23 06:03:54