2013-07-09 50 views
2

我使用的是NSFileManagerenumeratorAtPath方法來計算某些目錄下的文件大小。迭代使用filemanager的dirs佔用了相當多的內存

NSString *iterDir = @"/path/to/dir/"; 
NSFileManager *fm = [[NSFileManager alloc] init]; 
NSDirectoryEnumerator *dirEnum = [fm enumeratorAtPath:iterDir]; 

NSString *file; 
BOOL isDir; 
long long fileSize = 0; 
while (file = [dirEnum nextObject]) { 
    @autoreleasepool { 
     file = [iterDir stringByAppendingString:file]; 
     if ([fm fileExistsAtPath:file isDirectory:&isDir]) { 
      if (!isDir) { 
       NSError *error; 
       NSDictionary *attributes = [fm attributesOfItemAtPath:file error:&error]; 
       if (!error) { 
        fileSize += [attributes[@"NSFileSize"] doubleValue]; 
       } 
      } 
     } 
    } 
} 
NSLog(@"fileSize:%lld", fileSize); 

的結果是這樣的:

take many memory during while loop

有時是這樣的:

no returning memory

是用來做什麼的內存?爲什麼即使加上一個@autoreleasepool以外也沒有作用?

+0

找出導致它使用儀器的原因。然後回到這裏,因爲我很好奇。 – fumoboy007

回答

0

即使通過替換有效的目錄路徑,我也無法使您的示例按所提供的方式運行。你的代碼有一些問題。這裏有一些你需要做的改變。其一是這一行:

file = [iterDir stringByAppendingString:file]; 

這真的應該改爲:

file = [iterDir stringByAppendingPathComponent:file]; 

後者是非常非常安全,因爲它會正確地追加路徑,無論您的目錄路徑是否有結束/或不。 (您原來的失敗在我的情況,因爲我用[@"~/Desktop" stringByExpandingTildeInPath]讓我的目錄路徑;能產生無拖尾/的路徑。)

然後你的循環裏面,你在堆棧上分配未初始化變量error,傳遞它通過參考,然後詢問它是否是nil。這是一個錯誤的問題,因爲error的值不能保證,除非該方法返回nil(或者NO,取決於方法)。您應該詢問attributes是否爲nil,並通過NULLerror,因爲您似乎對此沒有興趣。所以總結起來,改變這種:

NSError *error; 
NSDictionary *attributes = [fm attributesOfItemAtPath:file error:&error]; 
if (!error) { 

這樣:

NSDictionary *attributes = [fm attributesOfItemAtPath:file error:NULL]; 
if (attributes != nil) { 

修復是第二個問題意味着您的結果將更加一致的,我保證。同時,當我運行代碼時,我得到的結果看起來可能是NSLog()語句中的有效值。

沒有什麼,你也可以使用快速枚舉爲你的循環。相反的:

while (file = [dirEnum nextObject]) { 

你也可以使用:

for (file in dirEnum) { 

現在對於你原來的問題。你分配的內存膨脹的原因是你的包含文件名的字符串被分配到你的@autoreleasepool指令的範圍之外,進入主自動釋放池,在那裏它們將一直坐到該池清空。不過,您仍然在循環內使用自己的autorelease池做了一件好事。

+0

感謝4您優化建議,他們真的很有幫助。但仍然無法修復/解釋內存問題。無法運行?你可以提供'/ Users/yourname/Desktop'這樣的絕對路徑。它應該做的工作。 – limboy

+0

絕對路徑會起作用,但是如果使用其他方法產生沒有尾部斜線的路徑,比如我使用了什麼呢? – trudyscousin

+0

當然'stringByAppendingPathComponent:'有效,但對結果沒有影響。 – limboy