iOS11下WKWebview读取相册图片无法上传问题求助
iOS 11 WKWebView 相册图片上传失败问题解析与解决方案
问题真实性确认
太懂这个坑了!你碰到的PlugInKit Code=13 "query cancelled"错误确实是iOS 11的一个已知Bug,不少用WKWebView做混合应用的开发者都栽过跟头。相机拍摄能正常上传是因为它的调用流程和相册的插件查询逻辑完全不同,刚好避开了这个Bug的触发点。
临时替代方案
这里有几个经过开发者验证的临时解决办法,你可以根据项目情况选择:
- 手动接管WKWebView的文件选择流程:通过实现WKWebView的
WKUIDelegate代理方法,绕过原生的文件选择弹窗,自己调用UIImagePickerController来选择相册图片,拿到图片后再把临时文件的URL传给WebView的回调。这是最靠谱的解决方案,完全避开了原生插件查询的Bug。 - 临时切换到UIWebView(仅应急用):如果项目时间紧张,暂时切换回UIWebView可以解决这个问题,但要注意UIWebView已经被苹果官方弃用,长期来看还是得用WKWebView的方案。
- 添加延迟触发:在前端JS触发文件选择的代码里,加一个200-300ms的延迟再调用文件选择API,部分开发者反馈这个方法能降低错误出现的概率,但不是100%有效,适合作为临时过渡方案。
代码示例(手动接管文件选择)
下面是Swift版本的实现示例,核心是自己处理相册选择逻辑:
// 先定义一个属性保存WebView的回调 private var openPanelCompletionHandler: (([URL]?) -> Void)? // 实现WKUIDelegate的文件选择代理方法 func webView(_ webView: WKWebView, runOpenPanelWith parameters: WKOpenPanelParameters, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping ([URL]?) -> Void) { // 保存回调,等选完图片再调用 openPanelCompletionHandler = completionHandler let picker = UIImagePickerController() picker.sourceType = .photoLibrary picker.delegate = self picker.allowsEditing = false // 根据需求调整是否允许编辑 // 假设当前控制器是self,记得提前设置好代理 present(picker, animated: true) } // 实现UIImagePickerControllerDelegate和UINavigationControllerDelegate extension YourViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate { func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { picker.dismiss(animated: true) guard let originalImage = info[.originalImage] as? UIImage, let tempFileURL = saveImageToTempDirectory(image: originalImage) else { openPanelCompletionHandler?(nil) return } // 把临时文件URL传给WebView的回调 openPanelCompletionHandler?([tempFileURL]) } func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { picker.dismiss(animated: true) openPanelCompletionHandler?(nil) } // 辅助方法:将图片保存到临时目录,生成可被WebView识别的URL private func saveImageToTempDirectory(image: UIImage) -> URL? { guard let imageData = image.jpegData(compressionQuality: 0.8) else { return nil } let tempDir = NSTemporaryDirectory() let fileName = "\(UUID().uuidString).jpg" let fileURL = URL(fileURLWithPath: tempDir).appendingPathComponent(fileName) do { try imageData.write(to: fileURL) return fileURL } catch { print("保存临时图片失败:\(error.localizedDescription)") return nil } } }
注意事项:
- 确保你的ViewController已经遵守
UIImagePickerControllerDelegate和UINavigationControllerDelegate协议;- info.plist里的
NSPhotoLibraryUsageDescription权限配置不能少,否则会触发崩溃。
内容的提问来源于stack exchange,提问作者nadim
相关产品推荐
相关产品推荐

