You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用AVFoundation读取含ASCII字符的QR码时stringValue返回nil的问题

解决加密ASCII字符QR码读取时stringValue返回nil的问题

看起来你遇到的核心问题是加密后的QR码包含非可打印ASCII字符,导致[metadataObj stringValue]无法正常解码成NSString,直接返回nil了。因为stringValue会尝试把QR码的原始字节按照标准字符串编码(比如UTF-8)去解析,而加密后的字节流大概率不是合法的字符串编码,所以这条路走不通。

先看你代码里的明显问题:

unsigned char buffer_to_decrypt=[metadataObj stringValue];

stringValue返回的是NSString*类型,你直接赋值给unsigned char变量,这不仅编译会报错,逻辑上也完全错误——你需要的是QR码存储的原始字节数据,而不是转成字符串后的内容。


正确处理方案:获取QR码原始字节数据

AVMetadataMachineReadableCodeObject提供了dataValue属性,它会直接返回QR码存储的原始字节NSData,不管这些字节是不是可打印ASCII字符,这才是你需要的加密数据载体。

修正后的代码如下:

-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{ 
    unsigned char myKey[2]; 
    myKey[0]=1; 
    myKey[1]=2; 

    if(metadataObjects == nil || [metadataObjects count] ==0) { 
        qrCodeFrameView.frame=CGRectZero;
        return; // 增加return避免后续无效执行
    }

    AVMetadataMachineReadableCodeObject *metadataObj = [metadataObjects objectAtIndex:0]; 
    if ([[metadataObj type] isEqualToString:AVMetadataObjectTypeQRCode]) { 
        // 关键:改用dataValue获取QR码原始字节数据
        NSData *encryptedData = metadataObj.dataValue;
        if (!encryptedData) {
            NSLog(@"无法获取QR码原始数据");
            qrCodeFrameView.frame=CGRectZero;
            return;
        }

        Encoder *encoder=[[Encoder alloc] init]; 
        NSLog(@"原始加密数据长度:%lu", (unsigned long)encryptedData.length);

        // 分配解密缓冲区,长度与加密数据一致
        NSUInteger dataLength = encryptedData.length;
        unsigned char *buffer_to_decrypt = malloc(dataLength);
        if (!buffer_to_decrypt) {
            NSLog(@"内存分配失败");
            return;
        }
        [encryptedData getBytes:buffer_to_decrypt length:dataLength];

        // 执行3DES解密(注意:3DES密钥长度要求16/24字节,当前2字节密钥不安全且可能导致解密失败)
        [encoder tripledes_decrypt:buffer_to_decrypt lenght:dataLength key:myKey]; 

        // 将解密后的字节转为NSData
        NSData *decryptedData = [NSData dataWithBytes:buffer_to_decrypt length:dataLength];
        NSLog(@"解密后data = %@", decryptedData); 

        // 转为ASCII字符串
        NSString *result=[[NSString alloc] initWithData:decryptedData encoding:NSASCIIStringEncoding]; 
        NSLog(@"-----<<<<result>>>>%@",result); 

        // 更新识别框并触发震动
        AVMetadataMachineReadableCodeObject *barCodeObj=(AVMetadataMachineReadableCodeObject *)[_videoPreviewLayer transformedMetadataObjectForMetadataObject:metadataObj]; 
        qrCodeFrameView.frame=barCodeObj.bounds; 
        AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); 
        [self stopReading]; 
        _isReading = NO; 

        // 释放手动分配的内存
        free(buffer_to_decrypt);
    } 
}

额外提醒

  1. 3DES密钥长度问题:当前你使用的2字节密钥不符合3DES算法要求(标准要求16或24字节),不仅完全没有安全性,还可能导致解密函数执行失败,建议立即修正密钥长度。
  2. 内存管理:代码中用malloc分配的缓冲区需要手动free,避免内存泄漏;ARC环境下NSData会自动管理内存,无需额外处理。
  3. QR码容量限制:加密后的数据长度不能超过目标QR码版本的容量上限,否则生成的QR码可能无法被正常识别。

内容的提问来源于stack exchange,提问作者hikmat_11

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:54:20