How to optimize directory listing? (enumeratorAtPath and recursive call contentsOfDirectoryAtPath)

后端 未结 3 1345
夕颜
夕颜 2021-01-14 14:46

I wrote a method(getDirTree1) that makes listing all directories from the root, using the recommended class NSDirectoryEnumerator and method nextObject. But while it was run

相关标签:
3条回答
  • 2021-01-14 15:22

    [directoryPath stringByAppendingPathComponent:filePath]; returns an autoreleased object. Since it's happening inside such a tight loop, all these objects are adding up and causing the large memory footprint in question. All you have to do to fix it is get rid of them more often. You can change your method to something that doesn't use autorelease, or you could just create your own, tight autorelease pool, like this:

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

    This will ensure that everything's released as soon as you no longer need it, avoiding the buildup of objects during the loop.

    (Interesting sidenote: NSPathStore2 is a private class related to NSString (which is a class cluster) used to store path-type strings. That's how I knew which method was at fault.)

    0 讨论(0)
  • 2021-01-14 15:39

    Easily use NSDirectoryEnumerator as documented here and shown here

    0 讨论(0)
  • 2021-01-14 15:41

    For anyone using automatic reference counting, if the following (which should be the equivalent of andyvn22's answer for ARC) doesn't work for you:

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

    I was able to solve it by doing this instead

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

    The code isn't as elegant as it could be, but the memory saving is.


    Update: Recently had problems with this again, what worked even better was this:

    file = [dirEnum nextObject];
    while (file) {
        @autoreleasepool {
            fullFilePath = [ directoryPath stringByAppendingPathComponent:filePath ];
            NSLog( @"%@ \n", fullPath );
            filePath = [ dirEnum nextObject ] );
        }
    }
    
    0 讨论(0)
提交回复
热议问题