其他
在 iOS 应用中使用 CoreNFC 读写 NFC…
当需要在 iPhone 上扫描、读取或写入 NFC 标签(NDEF、ISO7816、ISO15693、FeliCa、MIFARE)并处理会话生命周期与后台读取时使用。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 35/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 38/100 ×0.15
适用场景
在 iOS 应用中使用 CoreNFC 特定
解决思路
- 在 Xcode 中添加 Near Field Communication Tag Reading 能力。
- 在 Info.plist 中添加 NFCReaderUsageDescription,并提供面向用户的原因说明字符串。
- 添加 com.apple.developer.nfc.readersession.formats 权限,使用当前的 TAG 值;不要添加旧的 NDEF。
- 对于 ISO 7816 标签,在 Info.plist 的 com.apple.developer.nfc.readersession.iso7816.select-identifiers 中添加支持的应用标识符。
- 对于 FeliCa 标签,在 Info.plist 的 com.apple.developer.nfc.readersession.felica.systemcodes 中添加支持的系统码;不要使用通配符系统码。
- NFC 读取需要 iPhone 7 或更新机型;在创建 NFC UI 或会话之前,始终用即将创建的具体 reader session 类型检查 readingAvailable。
- 使用 NFCNDEFReaderSession 读取 NDEF 格式数据:创建会话时传入 delegate、queue 为 nil、invalidateAfterFirstRead 按需设置,设置 alertMessage 后调用 begin()。
- 实现 NFCNDEFReaderSessionDelegate:readerSessionDidBecomeActive 表示正在扫描;didDetectNDEFs 中遍历 message.records 处理记录;didInvalidateWithError 中区分用户取消与真实错误。
- 对于读写操作,使用 didDetect tags 委托方法:取 tags.first,若为空则调用 session.restartPolling();否则调用 session.connect(to: tag) 连接标签。
- 连接成功后调用 tag.queryNDEFStatus 查询状态:notSupported 时提示标签不兼容 NDEF;readOnly 时调用 tag.readNDEF 读取;readWrite 时读取后提示成功并 invalidate。
- 使用 NFCTagReaderSession 直接访问原生标签协议:.iso14443 对应 ISO 7816 兼容和 MIFARE,.iso15693 对应 ISO 15693,.iso18092 对应 FeliCa。
- 写入 NDEF 前先调用 tag.queryNDEFStatus,确认 status == .readWrite,否则提示只读并 invalidate。
- 构造写入内容:用 NFCNDEFPayload.wellKnownTypeURIPayload(url:) 创建 URL payload,用 NFCNDEFMessage(records:) 组装消息,再调用 tag.writeNDEF(message) 写入。
- 创建常见 payload:URL 用 wellKnownTypeURIPayload;文本用 wellKnownTypeTextPayload(string:locale:);自定义用 NFCNDEFPayload(format:.nfcExternal, type:identifier:payload:)。
- 后台标签读取(iPhone XS 及以后):NDEF 消息必须包含 URI 记录(typeNameFormat == .nfcWellKnown,type 为 U);多条 URI 记录时系统使用第一条。
- 后台路由使用 universal link 并配置 Associated Domains 能力,或使用系统支持的 URL scheme(web、email、SMS、telephone、FaceTime、Maps、HomeKit 设置);不支持自定义 URL scheme,也不按 bundle ID 或任意 NDEF 内容类型路由。
- 在 scene(_:continue:) 中处理后台标签数据:检查 userActivity.activityType == NSUserActivityTypeBrowsingWeb,读取 userActivity.ndefMessagePayload,跳过 typeNameFormat == .empty 的记录并遍历处理。
- 在 didInvalidateWithError 中过滤预期终止原因:readerSessionInvalidationErrorUserCanceled 和 readerSessionInvalidationErrorFirstNDEFTagRead 视为正常,不弹错误提示。
- 会话失效后将其引用置为 nil;再次扫描时创建新的 NFCNDEFReaderSession 并调用 begin(),不要复用已失效的会话。
- 同一时间只保持一个 reader session 处于活动状态。
- 写入大消息前检查标签容量。
- 使用 NFCTagReaderSession 时,若轮询 .iso18092 需在 Info.plist 中列出 FeliCa 系统码;若使用 ISO 7816 需列出应用标识符。
- 将支付相关的 AID 从 NFCTagReaderSession 中排除。
- 扩展模式(ISO 7816 命令、多标签扫描、NDEF 锁定)参考 references/nfc-patterns.md。
适用边界 · 注意事项
- 不要使用过时或缺失的 NFC 权限(例如旧示例中的 NDEF 值),否则 reader session 无法访问 NFC 硬件。
- 不要用 NFCTagReaderSession 处理支付相关的 AID。
- 不要用自定义 URL scheme、bundle ID 或任意 NDEF 内容类型做后台标签路由。