2013-05-16 11 views
0

这是我想要实现的。 1.搜索所有的文件2.找到所有.jpg文件的搜索3.在所有.jpg文件路径保存到NSMutableArray的目标c:在线程中将对象添加到NSMutableArray时出错

这里是代码:

  1. 创造了NSMutableArray中:

    NSMutableArray *jpgFiles = [[[NSMutableArray alloc]init]autorelease]; 
    
  2. 搜索下(/用户/)路径(开始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个文件后,它开始在最后给我错误和崩溃)。

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

以下是错误消息:

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

然而,甚至发生这种错误,它仍保持节省一些的路径然后它会抛出另一个错误:

An uncaught exception was raised 

你可以告诉我如何解决吗?谢谢 !!

+0

该错误指示内存管理问题。也许问题是在'jpgFiles'上使用'autorelease'。当你创建它时,不要使用'autorelease',而是在你真正完成阵列时调用'release'。 – rmaddy

+0

你是对的。谢谢 !!!! :]但是为什么我应该使用release而不是autorelease? –

+0

这是一个很大的问题。这个过于简单的原因是,在当前运行循环结束时会清除自动释放的对象。查看“NSObject autorelease”的文档。应该有一些其他文档的链接可以深入讨论。 – rmaddy

回答

1

首先,尝试通过随机产生线程来提高性能可以保证失败。并发性必须被考虑和控制。其次,试图通过同时访问所述资源而不受限制来减少访问慢资源(如文件系统)的代码的执行时间将比序列化访问慢。文件系统的I/O速度相对较慢,线性I/O总是比并发冲突的随机I/O更快。

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

+0

所以我的理解是在我使用文件系统时不使用线程。所以你会介绍简单介绍一下什么样的情况下使用NSThread是很好的。谢谢 –

+0

并发 - 线程或队列 - 很难。现在,你可能根本不使用NSThread,而是使用NSOperationQueue或GCD。适用的地方是整本书的主题!我建议从这里开始:https://developer.apple.com/library/mac/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/Introduction/Introduction.html – bbum

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

相关问题