2011-08-04 31 views
3

我寫了一個方法(getDirTree1),它使用建議的類NSDirectoryEnumerator和nextObject方法列出根目錄中的所有目錄。不過,雖然這是不可接受的運行使用大量的內存(主要是民營類NSPathStore2):如何優化目錄列表? (enumeratorAtPath和遞歸調用contentsOfDirectoryAtPath)

-(void) getDirTree1:(NSString*)directoryPath { 
    NSDirectoryEnumerator *dirEnum = [self->fileManager enumeratorAtPath:derectoryPath]; 
    NSString *filePath; 
    NSString *fullFilePath; 

    while ((filePath = [ dirEnum nextObject ]) != nil) { 
     fullFilePath = [ directoryPath stringByAppendingPathComponent:filePath ]; 
     NSLog(@"%@ \n", fullPath); 
} 

} 

假設這是因爲對象NSDirectoryEnumerator,我重寫方法(getDirTree2)。現在使用遞歸方法,NSArray類和objectEnumerator方法。 但是再次使用了大量的內存。

-(void) getDirTree2:(NSString*)directoryPath { 
    NSArray *contents = [ self->fileManager contentsOfDirectoryAtPath:directoryPath error:NULL ]; 
    NSEnumerator *enumeratorContent [ contents objectEnumerator ]; 
    NSString *file; 
    BOOL fileIsDirectory = FALSE; 

    while ((file = [ enumeratorContent nextObject ])) { 
     NSLog(@"%@ \n", [ directoryPath stringByAppendingPathComponent: file ]); 
     if ([ self->fileManager fileExistAtPath:[ directoryPath stringByAppendingPathComponent:file ] isDirectory:&fileIsDirectory ] && fileIsDirectory) 
      [ self getDirTree2:[ directoryPath stringByAppendingPathComponent: file ] ]; 
    } 
} 

我錯過了什麼(也許我必須dealloc /保留一些對象)以及如何做得更好。 謝謝。

回答

4

[directoryPath stringByAppendingPathComponent:filePath];返回自動釋放對象。由於它發生在如此緊密的循環中,所有這些對象都在累加,並造成大量內存佔用。你所需要做的就是更頻繁地去除它們。您可以將方法更改爲不使用自動釋放,或者你可以只創建你自己的,緊自動釋放池,像這樣:

while ((filePath = [ dirEnum nextObject ]) != nil) { 
    NSAutoreleasePool* pool = [NSAutoreleasePool new]; 
    fullFilePath = [ directoryPath stringByAppendingPathComponent:filePath ]; 
    NSLog(@"%@ \n", fullPath); 
    [pool drain]; 
} 

這將確保所有的發佈儘快你不再需要它,避免循環過程中物體的堆積。

(有趣的旁註:NSPathStore2是與用於存儲路徑型串NSString(這是一類簇)的私有類這就是我如何知道哪些方法有錯。)

+0

會如何,如果自動引用計數是這樣進行正在使用? – newenglander

+1

'@autoreleasepool {// code}' – andyvn22

+1

謝謝,已經嘗試過了,也許我錯過了其他的東西。我會再試一次,如果它不起作用,我會發佈一個問題。 – newenglander

4

對於使用自動人引用計數,如果以下(這應該是andyvn22的答案ARC等效)不爲你工作:

while ((filePath = [ dirEnum nextObject ]) != nil) { 
    @autoreleasepool { 
     fullFilePath = [ directoryPath stringByAppendingPathComponent:filePath ]; 
     NSLog(@"%@ \n", fullPath); 
    } 
} 

我能夠這樣做,而不是

解決呢
filePath = [ dirEnum nextObject ]); 
while (filePath != nil) {  
    @autoreleasepool { 
     fullFilePath = [ directoryPath stringByAppendingPathComponent:filePath ]; 
     NSLog(@"%@ \n", fullPath); 
     filePath = [ dirEnum nextObject ]); 
    } 
} 

代碼沒有儘可能優雅,但節省內存。


更新:最近又有了這個問題,什麼工作更好的是這樣的:

file = [dirEnum nextObject]; 
while (file) { 
    @autoreleasepool { 
     fullFilePath = [ directoryPath stringByAppendingPathComponent:filePath ]; 
     NSLog(@"%@ \n", fullPath); 
     filePath = [ dirEnum nextObject ]); 
    } 
}