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 上我的 fork 的 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]的现有调用)这种方式总是在发送所有数据后调用完成。

问候

于 2013-01-17T17:00:29.067 回答