我不太熟悉Objective-C,因此如果这是一个愚蠢的问题,请原谅我。我创建了一个后台线程来解析目录中存在的文件列表,该目录中的文件可以随时更改。

我在循环的每次迭代中都调用“contentsOfDirectoryAtPath”,而我的分配突然超过了300mb。我不知道如何使ARC释放返回的数组。有人可以在这里指出正确的方向吗?

-(void) offlineModeThread
{

    NSString *dataDir = [ViewController getDataDirectory];
    NSFileManager *nfm = [NSFileManager defaultManager];

    while(1)
    {
        NSArray *files = [nfm contentsOfDirectoryAtPath:dataDir error:nil];
        /*
        if(files == nil)
            break;

        if([files count] <= 0)
        {
            files = nil;
            [NSThread sleepForTimeInterval: 5.0f];
            continue;
        }

        if(![ViewController obtainLock])
        {
            files = nil;
            continue;
        }
        */
        //[ViewController releaseLock];
        files = nil;
    }

}

如您所见,我尝试通过将'files'设置为nil来释放数组,但是它不起作用。

最佳答案

您如何创建此线程? NSThread? NSOperation和NSOperationQueue? GCD?

对于NSThread和NSOperation,应该在设置线程的过程中创建自己的自动释放池。这样,可以在该线程内正确管理临时对象。

我相信GCD会为您处理这个细节。

在Objective C的较新版本(我相信Objective C 2.0)中,应使用新语法

@autoreleasepool
{
   //Code to use a local autorelease pool
}

对于生成大量临时对象的循环,可以为任何代码块创建本地自动释放池。您可以这样重构代码:
while(1)
{
  @autoreleasepool
  {
    NSArray *files = [nfm contentsOfDirectoryAtPath:dataDir error:nil];
    /*
    if(files == nil)
        break;

    if([files count] <= 0)
    {
        files = nil;
        [NSThread sleepForTimeInterval: 5.0f];
        continue;
    }

    if(![ViewController obtainLock])
    {
        files = nil;
        continue;
    }
    */
    //[ViewController releaseLock];
    files = nil;
  }
}

这将导致它为循环的每次迭代创建一个新的自动释放池,并在最后将其耗尽(从而释放该迭代中创建的所有临时对象)。

顺便说一句,如果您使用的是NSThread,请不要使用。了解如何改为使用GCD。 GCD(大中央调度)使MUCH比NSThread更有效地利用系统资源。 NSThread基于POSIX线程,这在创建时非常昂贵,并且会在应用程序生命周期内占用设备上的物理内存。

NSOperationQueues在最近的OS版本中已经过重构,可以在后台使用GCD,因此它们在内部的效率也类似,尽管在大多数情况下比GCD难使用。

关于ios - iOS —调用contentsOfDirectoryAtPath会在循环中泄漏内存,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20134951/

10-13 06:51