0

アプリの安定化に関するアドバイスを探しています。まず、いくつかの要件-PII(個人を特定する情報)を含むファイルは、ディスク上で暗号化する必要があります。タンブネイルとロゴはカスタム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にアクセスしようとしている2つのスレッドが存在する可能性があると思われます

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

常にすぐに発生するわけではありませんが、最終的に、セルのtableViewリストをスクロールすると、アプリが次のようにクラッシュします。*キャッチされない例外'NSGenericException'が原因でアプリを終了します。列挙された。」

セルに復号化された画像を含める必要があります。最初の解決策(上記)では、画像が利用可能になったときにこれを実行しますが、アプリがクラッシュします。すべてのスレッドを開始して取得および復号化する前に、画像を復号化してloadAndShowThumbnailImageでそのキャッシュをチェックしたときに、ある種のメモリ内キャッシュがこれを改善するのに役立つかどうか疑問に思っています。

考え?私はこれを1週間強打してきましたが、今ではさまざまなことを試しています。新鮮な視点をいただければ幸いです。

ありがとう。

4

1 に答える 1

0

Justins リンクとその後の調査に基づいて、私はこの方向に進みました: UITableView で、画面から消えたセルの GCD 操作をキャンセルする最良の方法は?

于 2012-09-04T22:36:12.023 に答える