2

iOS で RNCryptor を使用して大きなファイルを非同期で復号化する必要があります (プログレス バーを表示するため)。私はどこにも例を見つけられなかったので、私が正しいと推測したことを試しましたが...私が思いついたものは機能しません:復号化のハンドラーは決して呼び出されず、スレッドはすべてのデータを送信した後に EXC_BAD_ADDRESS でクラッシュしました関数の最後に。

NSOutputStream *decryptedStream = [NSOutputStream outputStreamToFileAtPath:decryptedPath append:NO];
[decryptedStream open];

NSUInteger totalBytesToRead = [[[NSFileManager defaultManager] attributesOfItemAtPath:tempPath error:nil] fileSize];
__block NSUInteger totalBytesRead = 0;

LOG("I've got %d bytes to decrypt.", totalBytesToRead);

RNDecryptor *decryptor = [[RNDecryptor alloc] initWithPassword:SNCatalogPassword handler:^(RNCryptor *cryptor, NSData *data) {
    totalBytesRead += data.length;
    [decryptedStream write:data.bytes maxLength:data.length];

    LOG("Decrypted %d bytes : %d / %d bytes treated", data.length, totalBytesRead, totalBytesToRead);

    if (cryptor.isFinished)
    {
        //proceed
        LOG("Done with decrypting.");

        [decryptedStream close];

    }
}];

// Feed data to the decryptor
NSInputStream *cryptedStream = [NSInputStream inputStreamWithFileAtPath:tempPath];
[cryptedStream open];
while (cryptedStream.hasBytesAvailable)
{
    uint8_t buf[4096];
    NSUInteger bytesRead = [cryptedStream read:buf maxLength:4096];
    NSData *data = [NSData dataWithBytes:buf length:bytesRead];
    LOG("Sending %d bytes to decryptor...", bytesRead);

    dispatch_async(dispatch_get_main_queue(), ^{
        [decryptor addData:data];
    });
}

LOG("Sent everything.");
[decryptor finish];
[cryptedStream close];

(明らかに、tempPathは暗号化されたファイルへのパスです。decryptedPathは復号化されたデータが書き込まれるパスです)。

また、私は ARC を初めて使用するので、これはメモリまたはディスパッチに関連する問題である可能性があります。

助けてくれてありがとう。

4

2 に答える 2

3

私は今日同じ問題に遭遇しました.iOS6でdispatch_get_current_queue()が最近廃止されたために発生しているようです.

[RNCryptor initWithHandler:] を変更して新しいキューを作成すると、復号化が正しく機能します。

NSString *responseQueueName = [@"net.robnapier.response." stringByAppendingString:NSStringFromClass([self class])];
_responseQueue = dispatch_queue_create([responseQueueName UTF8String], NULL);

github の私のフォークの async_decrypt ブランチで、修正と関連する単体テスト (コードに基づく) を見つけることができます。

csteynberg/RNCryptorにコミットする

于 2013-01-18T02:13:35.550 に答える
2

あなたの動作は非同期実行によるものです: addDataの呼び出しを行う前に[decryptor finish]を呼び出します: これを修正するには、置き換える必要があります

while (cryptedStream.hasBytesAvailable)
{
  //...

while (YES) {
  if (!cryptedStream.hasBytesAvailable) {
    dispatch_async(dispatch_get_main_queue(), ^{
      [decryptor finish];
    });
    break;
  }
  //...

(そしてもちろん[decryptor finish]への既存の呼び出しを削除します) このように、finish はすべてのデータが送信された後に常に呼び出されます。

よろしく

于 2013-01-17T17:00:29.067 に答える