Как оптимизировать список каталогов?(enumeratorAtPath и рекурсивный вызов contentOfDirectoryAtPath) - PullRequest
3 голосов
/ 04 августа 2011

Я написал метод (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 ] ];
   }
}

Что я пропустил (может быть, я должен освободить / сохранить некоторые объекты) и как сделать лучше. Спасибо.

Ответы [ 3 ]

4 голосов
/ 12 июня 2012

Для тех, кто использует автоматический подсчет ссылок, если следующее (что должно быть эквивалентно ответу andyvn22 для ARC) не работает для вас:

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

Iсмог решить ее, выполнив это вместо этого

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 ] );
    }
}
4 голосов
/ 04 августа 2011

[directoryPath stringByAppendingPathComponent:filePath]; возвращает автоматически освобожденный объект. Поскольку это происходит внутри такой тесной петли, все эти объекты складываются и вызывают большой объем памяти, о котором идет речь. Все, что вам нужно сделать, чтобы это исправить, это избавиться от них чаще. Вы можете изменить свой метод на тот, который не использует авто-релиз, или вы можете просто создать свой собственный, плотный авто-релиз, как этот:

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

Это гарантирует, что все будет выпущено , как только , как вам больше не нужно, избегая накопления объектов во время цикла.

(Интересная заметка: NSPathStore2 - это закрытый класс, связанный с NSString (который является кластером классов), используемый для хранения строк типа пути. Вот как я узнал, какой метод был ошибочным.)

0 голосов
/ 26 марта 2014

Легко использовать NSDirectoryEnumerator как , задокументированное здесь и , показанное здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...