如何使用SwiftUI编写Cordova iOS插件并展示Swift创建的界面
Cordova iOS插件展示SwiftUI界面实现方案
核心逻辑:Cordova iOS插件运行在WebView容器中,CDVPlugin类本身不直接管理视图层级,要展示SwiftUI编写的原生界面,必须通过Cordova持有的根视图控制器,用UIHostingController承载SwiftUI内容后弹出,仅初始化SwiftUI控件不挂载到视图层级不会有任何界面展示。
前置配置
- 确保插件工程已开启Swift编译支持,集成好CodeScanner组件
- 在iOS工程
Info.plist中添加NSCameraUsageDescription字段,描述相机使用用途,避免扫码功能触发权限崩溃
参考实现代码
import SwiftUI import CodeScanner // 自定义SwiftUI界面,可直接替换为扫码视图 @available(iOS 13.0, *) struct PluginContentView: View { var onDismiss: () -> Void var onResultCallback: (String) -> Void var body: some View { // 测试按钮,正式使用时替换为CodeScannerView即可 VStack(spacing: 20) { Button(action: { onResultCallback("操作成功") onDismiss() }) { Text("点击触发操作") .padding() .background(Color.blue) .foregroundColor(.white) .cornerRadius(8) } } // 扫码功能接入示例 // CodeScannerView(codeTypes: [.qr], completion: { response in // switch response { // case .success(let scanResult): // onResultCallback(scanResult.string) // onDismiss() // case .failure(let err): // onResultCallback("扫码失败:\(err.localizedDescription)") // onDismiss() // } // }) } } @available(iOS 13.0, *) @objc(ModusEchoSwift) class ModusEchoSwift : CDVPlugin { @objc(echo:) func echo(command: CDVInvokedUrlCommand) { // *所有UI操作必须切换到主线程执行,否则会出现界面不弹出、卡顿、崩溃问题 DispatchQueue.main.async { let contentView = PluginContentView( onDismiss: { [weak self] in self?.viewController.dismiss(animated: true) }, onResultCallback: { [weak self] result in let pluginResult = CDVPluginResult( status: CDVCommandStatus_OK, messageAs: result ) self?.commandDelegate!.send( pluginResult, callbackId: command.callbackId ) } ) let hostingVC = UIHostingController(rootView: contentView) if #available(iOS 13.0, *) { hostingVC.modalPresentationStyle = .fullScreen } self.viewController.present(hostingVC, animated: true) } } }
注意事项
- 不要在子线程执行任何UI相关操作
- 扫码场景建议将模态弹出样式设为全屏,避免默认半屏Sheet影响扫码体验
- 首次触发扫码时系统会自动弹出相机权限申请,无需额外手动触发
- 拿到扫码结果后要主动调用dismiss关闭原生界面,回到Cordova WebView页面
内容的提问来源于stack exchange,提问作者lorem_ipsum
相关产品推荐
相关产品推荐

