React Native NFC Manager iOS端快速取消后无法正常工作问题排查
React Native NFC Manager 快速重复触发无响应问题
我使用React Native NFC Manager开发基础NFC读取应用时遇到以下问题:点击TouchableOpacity启动扫描弹窗后,通过取消按钮关闭弹窗,若过快再次点击按钮,界面无任何反应,且无报错信息,推测该问题与NFC进程耗时有关。
原代码
import React, {useState} from 'react'; import {View, Text, TouchableOpacity, StyleSheet} from 'react-native'; import NfcManager, {NfcTech} from 'react-native-nfc-manager'; // Pre-step, call this before any NFC operations NfcManager.start(); function App() { const [loaded, setLoaded] = useState(true); async function readNdef() { try { setLoaded(false); // register for the NFC tag with NDEF in it await NfcManager.requestTechnology(NfcTech.Ndef); // the resolved tag object will contain `ndefMessage` property const tag = await NfcManager.getTag(); console.warn('Tag found', tag); } catch (ex) { console.warn('Oops!', ex); } finally { // stop the nfc scanning try { await NfcManager.cancelTechnologyRequest(); } catch (ex) { console.warn('Error while canceling technology request', ex); } finally { setLoaded(true); } } } return ( <View style={styles.wrapper}> {loaded && ( <TouchableOpacity onPress={readNdef}> <Text style={{color: 'white'}}>Scan a Tag</Text> </TouchableOpacity> )} </View> ); } const styles = StyleSheet.create({ wrapper: { flex: 1, justifyContent: 'center', alignItems: 'center', }, }); export default App;
问题原因
cancelTechnologyRequest是异步操作,快速重复触发时,前一次的取消操作尚未完成,后一次的requestTechnology已发起,导致NFC管理器处于状态不一致的情况。- 原代码中
setLoaded(true)是在finally块同步执行,未等待cancelTechnologyRequest完成,导致UI提前恢复可点击,但实际NFC进程还未清理完毕。
解决方案
通过新增状态跟踪NFC操作的实际状态,确保前一次所有NFC操作(包括取消)完成后,才允许触发下一次扫描:
import React, {useState} from 'react'; import {View, Text, TouchableOpacity, StyleSheet} from 'react-native'; import NfcManager, {NfcTech} from 'react-native-nfc-manager'; NfcManager.start(); function App() { const [isScanning, setIsScanning] = useState(false); async function readNdef() { // 防止重复触发 if (isScanning) return; setIsScanning(true); try { await NfcManager.requestTechnology(NfcTech.Ndef); const tag = await NfcManager.getTag(); console.warn('Tag found', tag); } catch (ex) { console.warn('Oops!', ex); } finally { // 等待取消操作完成后再更新状态 try { await NfcManager.cancelTechnologyRequest(); } catch (ex) { console.warn('Error while canceling technology request', ex); } finally { setIsScanning(false); } } } return ( <View style={styles.wrapper}> {!isScanning && ( <TouchableOpacity onPress={readNdef}> <Text style={{color: 'white'}}>Scan a Tag</Text> </TouchableOpacity> )} </View> ); } const styles = StyleSheet.create({ wrapper: { flex: 1, justifyContent: 'center', alignItems: 'center', }, }); export default App;
优化说明
- 使用
isScanning状态替代原loaded状态,统一管理扫描操作的状态。 - 在
readNdef函数开头增加判断,若当前正在扫描则直接返回,避免重复触发。 - 确保
cancelTechnologyRequest异步操作完成后,才将isScanning设为false,保证NFC进程完全清理后才允许下一次操作。
内容的提问来源于stack exchange,提问作者user19363667
相关产品推荐
相关产品推荐

