2012-09-01 18 views
0

尋求關於穩定我的應用程序的一些建議。首先一些要求 - 帶有PII(個人識別信息)的文件必須在磁盤上加密。 Tumbnails和徽標位於自定義TableViewCells中(如果可用),並且必須在顯示之前解密。線程正在查殺我的應用程序

有幾層線程正在進行。有一箇中心函數getFileData,用於檢查文件是否在設備上,或者是否需要從網絡獲取文件。我希望保持UI的響應和(我認爲)在於我的問題。

這裏是一些代碼: 這是在我的應用程序中處理文件的主力方法。它決定該文件是解密它並把它回回調:

-(void)fetchFileData:(UserSession *) session 
       onComplete: (void(^)(NSData* data)) onComplete 
{ 
    NSURL *url = [File urlForMail:self.fileId andSession:session]; 
    //NSLog(@"File id: %@", self.fileId); 
    NSString *encryptionKey = session.encryptionKey; 
    dispatch_queue_t cryptoQ = dispatch_queue_create(FILE_CRYPTOGRAPHY_QUEUE, NULL); 

    dispatch_async(cryptoQ, ^(void){ 
     // Get the file and d/encrypt it 
     NSError *error = nil; 
     if ([File fileExistsAtUrl:url] == YES) { 
      NSLog(@"file is on disk."); 
      NSData *localEncryptedFile = [File getDataForFile:url]; 
      NSData *decryptedFile = [RNDecryptor decryptData:localEncryptedFile 
               withPassword:encryptionKey 
                 error:&error]; 
      onComplete(decryptedFile); 
      dispatch_release(cryptoQ); 
     } else { 
      //NSLog(@"File is not on disk"); 
      NSDictionary *remoteFile = [session.apiFetcher getFileContent:self.fileId 
                   andToken:session.token]; 
      if (remoteFile && [[remoteFile objectForKey:@"success"] isEqualToString:@"true"]) {     
       NSData *remoteFileData = [remoteFile objectForKey:@"data"]; 
       NSString *mimeType = [remoteFile objectForKey:@"mimeType"]; 
       self.mimeType = mimeType; 
       NSData *encryptedData = [RNEncryptor encryptData:remoteFileData 
                withSettings:kRNCryptorAES256Settings 
                 password:encryptionKey 
                  error:&error]; 
       [encryptedData writeToURL:url atomically:YES]; 
       onComplete(remoteFileData); 
       dispatch_release(cryptoQ); 
      } 
     } 
    }); 

這裏是一個getFileData呼叫者的例子:

+(void)loadThumbnailForMail: (NSNumber*)thumbnailId 
        session: (UserSession*)session 
        callback: (void(^)(NSData* data))callback 
{ 
    File *file = [File findFile:thumbnailId inContext:session.mailDatabase.managedObjectContext];  
    dispatch_queue_t fetchQ = dispatch_queue_create(FILE_FETCHER_QUEUE_LABEL, NULL); 
    dispatch_async(fetchQ, ^(void) { 
     if (file) { 
      [file fetchFileData:session onComplete:^(NSData *data) { 
       if (data && file.mimeType) { 
        callback(data); 
       } 
      }]; 
     }   
    });  
    dispatch_release(fetchQ);  
} 

這裏是正在調用loadThumbnailForMail的TableViewCell的例子:

-(void)loadAndShowThumbnailImage:(Mail*) mail 
{ 
    UIImage *placeHolder = [UIImage imageNamed:@"thumbnail_placeholder.png"]; 
    [self.thumbnailImageForMail setImage:placeHolder]; 
    dispatch_queue_t loaderQ = dispatch_queue_create(THUMBNAIL_FETCHER, NULL); 
    dispatch_async(loaderQ,^{ 
     [File loadThumbnailForMail: mail.thumbnailId 
          session: [UserSession instance] 
          callback: ^(NSData *data) { 
           dispatch_async(dispatch_get_main_queue(), ^{ 
            UIImage *thumbnailImage = [UIImage imageWithData:data]; 
            [self.thumbnailImageForMail setImage:thumbnailImage]; 
           }); 
         }]; 
    }); 
    dispatch_release(loaderQ); 
} 

我認爲我的問題是我的loadThumbnailImage中的回調。如果用戶滾動速度不夠快,我懷疑,有可能是兩個線程試圖訪問同一TableViewCell

(MyCell *cell = (MyCell*)[tableView dequeueReusableCellWithIdentifier:CellTableIdentifier];) 

它並不總是發生立即但最終,經過一番滾動細胞的應用程序崩潰與的tableView列表這個:*由於未捕獲的異常'NSGenericException'而終止應用程序,原因:'*收集< __NSCFSet:0xde6a650>在枚舉時發生了變化。

我需要在單元格中具有解密的圖像,並且當圖像可用但第一個解決方案(上圖)會爲應用程序崩潰時執行此操作。我想知道是否某種內存緩存可以幫助改善這種情況,如果我在解密時將圖像放在內存中,並在啓動所有線程以獲取和解密它們之前檢查loadAndShowThumbnailImage中的緩存。

想法?我一直在爲此嘗試了不同的事情,並感謝一些新的觀點。

謝謝。

+0

由於有消息稱,你不能突變的集合(或陣列/字典),而它的被枚舉......這可發生在後臺線程正在改變前臺線程正在迭代的集合時。你能否將相關數據結構的副本傳遞給後臺線程? – nielsbot

+0

後臺線程只能在NSData對象上工作(除非在我使用的[link] https://github.com/rnapier/RNCryptor庫中還有別的事情發生,我還沒有看到它太深,只是足以確保它對我的需求來說確實足夠安全我在想,枚舉的數組/字典在主線程中,並且唯一要迭代的對象是託管對象的一個​​屬性,我稱其爲File: @property(nonatomic,retain)NSSet *郵件; – hippeelee

+0

必須有一個共享設置才能彈出這個錯誤,我自己打這個,深入挖掘一下,看看能不能找到共享對象 – nielsbot

回答

相關問題