cordova-plugin-camera在iOS取消选图时崩溃,报“No Image Selected”错误求助
解决iOS上cordova-plugin-camera取消操作导致的崩溃问题
我之前也碰到过一模一样的情况,这个崩溃的根源是:当用户在iOS上取消拍照/相册选图时,cordova-plugin-camera返回了NSNull对象,但@ionic-native/camera的5.x版本或者你的业务代码没有正确处理这个空值,导致后续代码尝试把NSNull当作字符串来处理,触发了OC层面的-[NSNull UTF8String]: unrecognized selector异常,直接导致应用崩溃。
下面是几个经过验证的解决思路:
1. 在业务代码中添加空值防护(最快见效)
检查你调用相机的代码,确保在成功回调和错误回调里都处理“取消”的场景,避免对空值执行字符串相关操作:
import { Camera, CameraOptions } from '@ionic-native/camera/ngx'; // ... const options: CameraOptions = { // 你的相机配置 quality: 80, destinationType: this.camera.DestinationType.DATA_URL, encodingType: this.camera.EncodingType.JPEG, mediaType: this.camera.MediaType.PICTURE }; this.camera.getPicture(options).then((imageData) => { // 先判断imageData是否为空,避免后续操作崩溃 if (!imageData) { console.log('用户取消了图片选择'); return; } // 正常处理图片逻辑,比如转成base64显示 const base64Image = 'data:image/jpeg;base64,' + imageData; // ... }).catch((err) => { // 处理错误时,区分“取消操作”和其他真实错误 if (!err || err === 'No Image Selected') { // 用户取消,无需报错,直接返回 return; } // 其他错误(比如权限问题、相机故障)再做处理 console.error('相机操作出错:', err); });
2. 升级插件到兼容版本
你当前使用的cordova-plugin-camera@4.1.0是比较旧的版本,后续版本已经修复了iOS取消时返回NSNull的问题。可以尝试升级到兼容的新版本:
首先卸载旧插件:
ionic cordova plugin remove cordova-plugin-camera npm uninstall @ionic-native/camera
然后安装匹配的新版本(注意Ionic 5对应@ionic-native 5.x,所以要安装5.x的最新兼容版):
npm install @ionic-native/camera@5.x ionic cordova plugin add cordova-plugin-camera@5.x
升级后测试取消操作,大部分情况下这个崩溃会直接消失。
3. 手动修改插件iOS源码(临时补丁)
如果暂时无法升级插件,可以手动修改cordova-plugin-camera的iOS代码,让它在取消时返回有效的错误字符串而不是NSNull:
- 找到项目中的
plugins/cordova-plugin-camera/src/ios/CDVCamera.m文件 - 搜索处理取消的代码块,找到类似下面的代码:
if (pickerSourceType == UIImagePickerControllerSourceTypeCamera) { [self dismissViewControllerAnimated:YES completion:^{ [command sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:nil]]; }]; }
- 将
messageAsString:nil改成messageAsString:@"Canceled"或者@"No Image Selected",这样上层代码拿到的是一个字符串而不是NSNull,就不会触发崩溃了:
[command sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Canceled"]];
注意:这种修改会在插件更新时被覆盖,如果你需要长期保留这个补丁,可以用patch-package工具来给插件打本地补丁。
内容的提问来源于stack exchange,提问作者Etienne Ctrs
相关产品推荐
相关产品推荐

