Expo iOS中react-native-signature-canvas报错:无法打开URL问题求助
解决Expo环境下react-native-signature-canvas的"Unable to open URL"错误
我之前也踩过这个坑!直接用官网的通用示例在Expo里跑确实会触发这个错误,核心原因是Expo的WebView不支持组件默认使用的自定义URL Scheme通信方式——组件内部用ReactABI32_0_0-js-navigation://postMessage这类协议传递签名数据,但Expo对WebView的跳转权限做了限制,导致无法解析这个URL。
下面是亲测有效的修复方案:
1. 替换通信方式,用Expo WebView标准API传递数据
放弃组件默认的自定义URL跳转,改用Expo WebView支持的postMessage/onMessage机制来传递签名数据。具体步骤:
- 使用
expo-webview(而非原生react-native-webview,Expo环境下适配性更好) - 给SignatureCanvas的
webviewProps注入自定义JS,替换原有的保存/清空逻辑为window.ReactNativeWebView.postMessage - 通过
onMessage回调接收签名数据
2. 完整可运行代码示例
import React, { useState, useRef } from 'react'; import { View, Button, Text } from 'react-native'; import SignatureCanvas from 'react-native-signature-canvas'; import { WebView } from 'expo-webview'; export default function SignatureDemo() { const [signatureBase64, setSignatureBase64] = useState(null); const signatureRef = useRef(null); // 处理WebView传递的签名数据 const handleWebViewMessage = (event) => { try { const messageData = JSON.parse(event.nativeEvent.data); if (messageData.type === 'SAVED') { // 拿到签名的base64字符串 setSignatureBase64(messageData.base64); } else if (messageData.type === 'CLEARED') { setSignatureBase64(null); } } catch (err) { console.error('解析签名数据失败:', err); } }; // 自定义签名画布样式 const customWebStyle = ` .m-signature-pad--footer { display: flex; gap: 10px; padding: 10px; } .m-signature-pad--body { border: 2px solid #2196F3; border-radius: 8px; } button { padding: 8px 16px; border: none; border-radius: 4px; cursor: pointer; } #save { background-color: #2196F3; color: white; } #clear { background-color: #f44336; color: white; } `; return ( <View style={{ flex: 1, padding: 20 }}> <SignatureCanvas ref={signatureRef} webStyle={customWebStyle} // 注入JS替换原有的URL跳转逻辑 webviewProps={{ onMessage: handleWebViewMessage, injectedJavaScript: ` // 替换保存按钮的点击事件 document.getElementById('save').addEventListener('click', () => { const canvas = document.querySelector('canvas'); const base64 = canvas.toDataURL('image/png'); window.ReactNativeWebView.postMessage(JSON.stringify({ type: 'SAVED', base64: base64 })); }); // 替换清空按钮的点击事件 document.getElementById('clear').addEventListener('click', () => { window.ReactNativeWebView.postMessage(JSON.stringify({ type: 'CLEARED' })); }); ` }} /> <View style={{ marginTop: 20, alignItems: 'center' }}> {signatureBase64 ? ( <Text style={{ color: '#2E7D32' }}>签名已保存 ✅</Text> ) : ( <Text style={{ color: '#757575' }}>请在上方绘制签名</Text> )} <Button title="手动清空签名" onPress={() => signatureRef.current?.clearSignature()} style={{ marginTop: 10 }} /> </View> </View> ); }
3. 额外注意事项
- 确保安装了
expo-webview:执行npx expo install expo-webview - 测试时使用Expo Go或自定义开发客户端,Web环境下WebView的通信逻辑略有不同
- 若使用较旧的Expo SDK版本,注意对应
react-native-signature-canvas的版本兼容性(建议使用最新稳定版)
内容的提问来源于stack exchange,提问作者Bhushan Patil




