如何优化目录列表? (enumeratorAtPath和递归调用contentsOfDirectoryAtPath)

时间:2011-08-04 14:37:49

标签: objective-c

我编写了一个方法(getDirTree1),它使用推荐的类NSDirectoryEnumerator和方法nextObject列出了根目录下的所有目录。但是当它运行不可接受时使用了大量内存(主要是私有类NSPathStore2):

-(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 /保留一些对象)以及如何做得更好。 感谢。

3 个答案:

答案 0 :(得分:4)

[directoryPath stringByAppendingPathComponent:filePath];返回一个自动释放的对象。由于它发生在这样一个紧密的循环中,所有这些对象都在加起来并导致大量的内存占用。你需要做的就是更频繁地摆脱它们。您可以将方法更改为不使用自动释放的方法,或者您可以创建自己的紧密自动释放池,如下所示:

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

这将确保您不再需要的所有内容尽快发布,避免在循环过程中构建对象。

(有趣的旁注:NSPathStore2是一个与用于存储路径类型字符串的NSString(类集群)相关的私有类。这就是我知道哪种方法有问题的方法。)< / p>

答案 1 :(得分: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 ] );
    }
}

答案 2 :(得分:-1)

轻松使用NSDirectoryEnumerator作为documented hereshown here