Swift中如何将URL以正确格式写入NFC标签
NFC URL写入Payload格式错误修正方案
你遇到的问题来源于两个核心错误:
- 错误混用了NDEF文本记录和URI记录的构造规则:最开始的
\u{02}en是NDEF文本记录的固定前缀(状态字节+语言码),完全不适用于URI类型记录 - 构造
NFCNDEFPayload时type参数传空,导致系统无法正确识别为URI记录,payload长度解析错误出现内容截断。你之前仅去掉\u{02}en前缀仍然出现截断,就是因为这个参数错误导致的。
正确的URI类型NDEF记录构造规则
NFC Well Known类型的URI记录必须满足以下要求:
type参数必须传入Data("U".utf8),标识这是URI类型记录- payload的第一个字节为URI前缀压缩码,常用压缩码对应关系:
- 0x00:无前缀,后续跟完整URI字符串
- 0x01:http://www.
- 0x02:https://www.
- 0x03:http://
- 0x04:https://
- 第一个字节之后跟剩余URI内容的UTF8编码数据
修正后的完整代码
private func writeTag(_ tag: NFCNDEFTag, for session: NFCReaderSession?) { guard let rawUrl = self.url, !rawUrl.isEmpty else { session?.invalidate(errorMessage: "URL is empty") return } var payloadData = Data() // 可根据实际URL前缀匹配对应压缩码,也可直接用0x00加完整URL if rawUrl.hasPrefix("https://") { payloadData.append(0x04) let suffix = String(rawUrl.dropFirst(8)) guard let suffixData = suffix.data(using: .utf8) else { session?.invalidate() return } payloadData.append(suffixData) } else if rawUrl.hasPrefix("http://") { payloadData.append(0x03) let suffix = String(rawUrl.dropFirst(7)) guard let suffixData = suffix.data(using: .utf8) else { session?.invalidate() return } payloadData.append(suffixData) } else { payloadData.append(0x00) guard let fullData = rawUrl.data(using: .utf8) else { session?.invalidate() return } payloadData.append(fullData) } // 注意type参数传入"U"的UTF8数据 let record = NFCNDEFPayload( format: .nfcWellKnown, type: Data("U".utf8), identifier: Data(), payload: payloadData ) let myMessage = NFCNDEFMessage(records: [record]) tag.writeNDEF(myMessage) { error in if let error = error { session?.invalidate(errorMessage: "Couldn't write tag: \(error.localizedDescription)") } else { session?.alertMessage = "Tag is written successfully" session?.invalidate() } } }
内容的提问来源于stack exchange,提问作者MaryLitv21
相关产品推荐
相关产品推荐

