Flutter NFC在iOS14.6报错:com.apple.nfcd.service.corenfc连接失效
Flutter开发的NFC功能在Android设备上运行正常,但在iOS 14.6设备上触发如下XPC错误:
XPC Error: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.nfcd.service.corenfc was invalidated from this process." UserInfo={NSDebugDescription=The connection to service named com.apple.nfcd.service.corenfc was invalidated from this process.}
相关实现代码
@override void initState() { super.initState(); _registerNFC(); } void _registerNFC() async { NfcManager.instance.startSession( pollingOptions: { NfcPollingOption.iso14443, NfcPollingOption.iso15693, NfcPollingOption.iso18092, }, onDiscovered: (NfcTag tag) async { print(tag.toString()); String mytag = ""; if (tag.data.containsKey("mifareclassic")) { mytag = tag.data["mifareclassic"]["identifier"] .map((e) => e.toRadixString(16).padLeft(2, '0')) .join('') .toString() .toUpperCase(); print("classic"); } else if (tag.data.containsKey("mifareultralight")) { mytag = tag.data["mifareultralight"]["identifier"] .map((e) => e.toRadixString(16).padLeft(2, '0')) .join('') .toString() .toUpperCase(); print("ultralight"); } else if (tag.data.containsKey("mifareplus")) { mytag = tag.data["mifareplus"]["identifier"] .map((e) => e.toRadixString(16).padLeft(2, '0')) .join('') .toString() .toUpperCase(); print("plus"); } else if (tag.data.containsKey("mifaredesfire")) { mytag = tag.data["mifaredesfire"]["identifier"] .map((e) => e.toRadixString(16).padLeft(2, '0')) .join('') .toString() .toUpperCase(); print("des fire"); } else { mytag = 'unknown type card'; } result.value = mytag; uid = result.value; NfcManager.instance.stopSession(); print("close session"); _updateNFC(); try { // await ndef.write(message); result.value = 'Success to "Ndef Write"'; NfcManager.instance.stopSession(); //_ndefWriteLock(); jangan letak kalau tak nnt tak boleh unlock balik } catch (e) { result.value = e; NfcManager.instance .stopSession(errorMessage: result.value.toString()); return; } }); } void _updateNFC() { if (uid != 'unknown type card') { Navigator.pop(context, uid); } else { CustomDialog.show(context, isDissmissable: false, title: "Unknown NFC tag", description: "Please use another type. Type allowed: [MifareClassic] [MifareUltralight] [MifareDesFire]", btnOkText: "I Understand", btnOkOnPress: () { Navigator.pop(context); print("open session"); _registerNFC(); }); } }
Info.plist配置
<key>NFCReaderUsageDescription</key> <string>to scan the NFC Tag on the fire extinguisher</string> <key>UIRequiredDeviceCapabilities</key> <array> <string>nfc</string> </array> <key>com.apple.developer.nfc.readersession.felica.systemcodes</key> <array> <string>0003</string> <string>04D1</string> <string>8008</string> <string>80DE</string> <string>865E</string> <string>8592</string> <string>8B5D</string> <string>8FC1</string> <string>FE00</string> </array> <key>com.apple.developer.nfc.readersession.formats</key> <array> <string>TAG</string> <string>NDEF</string> </array> <key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key> <array> <string>A0000002310100000000000000000000</string> <string>A0000002310200000000000000000000</string> <string>A0000002480300000000000000000000</string> </array>
已尝试更换flutter_nfc_kit包,但问题依旧,寻求正确配置和解决方法。
1. 修复重复调用stopSession的问题
代码中onDiscovered回调里连续调用了两次stopSession:
- 第一次在标签解析完成后立即调用
- 第二次在try块中再次调用
iOS的CoreNFC不允许重复关闭已失效的会话,这会直接触发XPC连接失效错误。修改方式:
- 移除多余的
stopSession调用,确保每个会话只关闭一次 - 将会话关闭逻辑统一放在业务逻辑执行完成后
修改后的核心代码片段:
onDiscovered: (NfcTag tag) async { print(tag.toString()); String mytag = ""; // 标签解析逻辑保持不变 result.value = mytag; uid = result.value; print("close session"); try { // 若有写操作,确保操作完成后再关闭会话 // await ndef.write(message); result.value = 'Success to "Ndef Write"'; NfcManager.instance.stopSession(); } catch (e) { result.value = e; NfcManager.instance.stopSession(errorMessage: result.value.toString()); return; } _updateNFC(); });
2. 精简Info.plist的NFC权限配置
当前配置包含大量不需要的NFC格式支持,可能导致CoreNFC会话初始化异常:
- 移除
com.apple.developer.nfc.readersession.felica.systemcodes和com.apple.developer.nfc.readersession.iso7816.select-identifiers配置项(仅需支持Mifare系列标签) - 保留
com.apple.developer.nfc.readersession.formats的TAG和NDEF即可
修改后的Info.plist关键配置:
<key>NFCReaderUsageDescription</key> <string>to scan the NFC Tag on the fire extinguisher</string> <key>UIRequiredDeviceCapabilities</key> <array> <string>nfc</string> </array> <key>com.apple.developer.nfc.readersession.formats</key> <array> <string>TAG</string> <string>NDEF</string> </array>
3. 避免会话未完全关闭时重启会话
_updateNFC方法中,识别到未知标签后立即调用_registerNFC()重启会话,iOS要求必须等待前一个会话完全关闭后才能启动新会话,否则会触发XPC连接失效。
修改方式:
- 等待会话完全关闭后再启动新会话,可添加短暂延迟或使用异步等待
示例修改:
// 修改stopSession调用为异步等待 await NfcManager.instance.stopSession(); print("close session"); // 再执行_updateNFC逻辑 // 弹窗回调中调整: btnOkOnPress: () async { Navigator.pop(context); await Future.delayed(Duration(milliseconds: 300)); print("open session"); _registerNFC(); }
4. 适配iOS 14的NFC会话生命周期
iOS 14对NFC会话生命周期管理更严格,需注意:
- 不在
initState中直接启动会话,改用WidgetsBinding.instance.addPostFrameCallback等待页面渲染完成后启动 - 页面销毁时必须关闭会话,避免内存泄漏和连接失效
添加页面销毁时的会话清理:
@override void dispose() { NfcManager.instance.stopSession(); super.dispose(); }
内容的提问来源于stack exchange,提问作者WizardKing Sekke

