Objective c 目标c:在线程过程中将对象添加到NSMutableArray时出错

Objective c 目标c:在线程过程中将对象添加到NSMutableArray时出错,objective-c,cocoa,nsmutablearray,nsfilemanager,nsthread,Objective C,Cocoa,Nsmutablearray,Nsfilemanager,Nsthread,这就是我想要实现的目标。1.搜索所有文件2。在搜索过程中查找所有.jpg文件3。将所有.jpg文件路径保存到NSMutableArray中 代码如下: 创建了NSMutableArray: NSMutableArray *jpgFiles = [[[NSMutableArray alloc]init]autorelease]; 正在(/Users/)路径下搜索所有父文件夹(在此处启动NSThread): 错误:(在开始时,它工作正常,并将许多不同的文件保存到数组中,但在保存了大约50个文

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

代码如下:

  • 创建了NSMutableArray:

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

  • 错误:(在开始时,它工作正常,并将许多不同的文件保存到数组中,但在保存了大约50个文件后,它开始给我错误,并在最后崩溃)

  • 以下是添加到数组中的正确元素:

    -(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]];
              }
           }
        }    
     }
    
        /Users/NAME/Documents/Graduate Books/IMG_2517.JPG
    
    以下是错误消息:

        -[NSPathStore2 addObject:]: unrecognized selector sent to instance 0x10011d4d0
    
    但是,即使发生此错误,它仍会将一些路径保存到数组中,然后会抛出另一个错误:

        An uncaught exception was raised
    

    你们能告诉我怎么修吗??谢谢

    首先,试图通过随机生成线程来提高性能肯定是失败的。必须考虑并控制并发性

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


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

    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线程”加载它们。

    此错误表示内存管理问题。问题可能是在
    jpgFiles
    上使用
    autorelease
    。创建数组时,不要使用
    autorelease
    ,而是在真正使用完数组后调用
    release
    。您是正确的。谢谢!!!!:]但是为什么我应该使用释放而不是自动释放?这是一个大问题。这个过于简单的原因是自动释放的对象将在当前运行循环结束时被清除。请参阅文档以了解
    NSObject autorelease
    。应该有一些其他文档的链接来深入介绍这一点,所以我的理解是在使用文件系统时不使用线程。所以,请您简要介绍一下什么样的情况下使用NSThread是好的。ThanksConcurrency——线程或队列——很难实现。现在,您可能根本不使用NSThread,而是使用NSOperationQueue或GCD。如果适用,则是整本书的主题!我建议从这里开始:
    - (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;
    }