0

这是我想要实现的目标。1. 搜索所有文件 2. 搜索过程中找到所有 .jpg 文件 3. 将所有 .jpg 文件路径保存到 NSMutableArray

以下是代码:

  1. 创建了 NSMutableArray:

    NSMutableArray *jpgFiles = [[[NSMutableArray alloc]init]autorelease]; 
    
  2. 搜索 (/Users/) 路径下的所有父文件夹(在此处启动 NSThread):

    NSString* filePath = [url path];
    NSArray *dirFiles = [[NSFileManager defaultManager]contentsOfDirectoryAtPath:filePath error:nil];
    
    if([dirFiles count]!=0)
    {
       for (int j=0; j<[dirFiles count]; j++) {
    
        NSString* pathExtension = [[dirFiles objectAtIndex:j] pathExtension];
    
        //if extension is null, we forwards to next level.
        if ([pathExtension isEqualTo:@""])
        {
            @autoreleasepool {
                [NSThread detachNewThreadSelector:@selector(searchingPicture:) toTarget:self withObject:[filePath stringByAppendingPathComponent:[dirFiles objectAtIndex:j]]];
            }
        }
        else
        {
            //if find jpg in this level, save into array
            if([pathExtension isEqualTo:@"JPG"])
            {
                [jpgFiles addObject:[filePath stringByAppendingPathComponent:[dirFiles objectAtIndex:j]]];
            }
        }
      }
    }  
    
  3. 继续搜索其余的子文件夹并将正确的文件路径保存到数组中:

    -(void)searchingPicture:(NSString*)path
     {
       NSFileManager *fileManager = [[[NSFileManager alloc] init] autorelease];
    
       NSURL *directoryURL = [NSURL URLWithString:[path stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
    
       NSArray *keys = [NSArray arrayWithObject:NSURLIsDirectoryKey];
    
       NSDirectoryEnumerator *enumerator = [fileManager
                                     enumeratorAtURL:directoryURL
                                     includingPropertiesForKeys:keys
                                     options:0
                                     errorHandler:^(NSURL *url, NSError *error) {
                                         // Handle the error.
                                         // Return YES if the enumeration should continue after the error.
                                         return YES;
                                     }];
    
      for (NSURL *url in enumerator) {
          NSError *error;
          NSNumber *isDirectory = nil;
          if (! [url getResourceValue:&isDirectory forKey:NSURLIsDirectoryKey error:&error]) {
               // handle error
           }
           else if (! [isDirectory boolValue]) {
              // No error and it’s not a directory; do something with the file
              if([[[url path] pathExtension]isEqualTo:@"JPG"])
              {
                  //This line gives me error !!!
                  [jpgFiles addObject:[url path]];
              }
           }
        }    
     }
    
  4. 错误:(一开始,它工作正常并将许多不同的文件保存到数组中,但在保存了大约 50 个文件后,它开始给我错误并在最后崩溃)。

这是添加到数组中的正确元素:

    /Users/NAME/Documents/Graduate Books/IMG_2517.JPG

这是错误消息:

    -[NSPathStore2 addObject:]: unrecognized selector sent to instance 0x10011d4d0

但是,即使发生此错误,它仍然会不断将一些路径保存到数组中,然后会引发另一个错误:

    An uncaught exception was raised

大家能告诉我怎么解决吗??谢谢 !!

4

2 回答 2

1

首先,尝试通过随机产生线程来提高性能肯定会失败。必须考虑和控制并发性。

其次,试图通过无约束地同时访问所述资源来减少访问慢速资源(如文件系统)的代码的执行时间将比序列化访问慢。文件系统的 I/O 相对较慢,线性 I/O 总是比并发的、冲突的、随机的 I/O 快。

最后,NSMutableDictionary不是线程安全的。其他可变集合类也不是。如果您从多个线程将内容塞入集合中,您将看到未定义的行为(通常是崩溃)。

于 2013-05-16T05:39:51.583 回答
0

NSMutableArray不是线程安全的。当你正确地保护它时它是线程安全的——所以任何时候都不能有超过一个线程能够使用它。

为了显示:

- (void)addPath:(NSString *)pPath
{
  [self.lock lock];
  [self.files addObject:pPath];
  [self.lock unlock];
}

- (NSUInteger)countPaths
{
  [self.lock lock];
  const NSUInteger count = self.files.count;
  [self.lock unlock];
  return count;
}

- (NSArray *)copyPaths
{
  [self.lock lock];
  NSArray * paths = [self.files copy];
  [self.lock unlock];
  return paths;
}

正如 bbum 所指出的,在您的示例中看到的目录枚举并不是一个非常适合并行化的问题——并行化在这种情况下会受到伤害。一种更实用的方法是仅从一个线程进行枚举。如果您想立即加载一些图像,也只需从“I/O 线程”加载它们。

于 2013-05-16T06:38:15.963 回答