2013-05-16 13 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線程」加載它們。

相關問題