使用CoreNFC写入iCode Slix2 NFC标签稳定性问题求助
iOS CoreNFC 写入iCode Slix2标签失败问题排查与解决
错误含义解析
- Error Code 100(Tag connection lost):设备与标签的NFC连接中断,多因标签距离过远、位置移动,或连续指令发送间隔过短导致标签来不及响应。
- Error Code 102(ISO15693TagResponseErrorCode=15):ISO 15693标准中,错误码15对应**"Write not allowed"**,说明目标块处于锁定状态,或标签写保护机制被触发,无法执行写入/擦除操作。
- Error Code 401(Stack Error):底层NFC栈连接意外关闭,多由上层指令发送逻辑不合理导致连接不稳定。
代码问题与优化方案
1. 连续块写入无间隔导致标签过载
当前递归连续写入块的逻辑未给标签留出处理时间,高频指令会导致标签过载断开连接。
优化:每次写入后添加50-100ms延迟:
func write(data: Data, to tag: NFCISO15693Tag, at block: UInt8) async throws { print("🏷️", "Writing data:", data, data.hexEncodedString(.upperCase), "at block:", block) try await tag.writeSingleBlock(requestFlags: [.highDataRate], blockNumber: block, dataBlock: data) // 给标签预留处理时间 try await Task.sleep(nanoseconds: 50_000_000) }
2. 缺失块锁定状态检查
iCode Slix2部分系统块默认锁定,或之前操作设置了用户块锁定,直接写入会触发错误码15。
补充逻辑:先检查块锁定状态,跳过或解锁后再写入:
func getBlockLockStatus(from tag: NFCISO15693Tag, block: UInt8) async throws -> Bool { let blockData = try await tag.readSingleBlock(requestFlags: [], blockNumber: block) // 参考iCode Slix2手册解析锁定位,示例为第7位 return blockData[0] & 0x80 != 0 } // 修改erase函数中的writeNextBlock逻辑 func writeNextBlock() async throws { if blockNumber < totalBlocks { alertMessage = "ERASING TAG \(blockNumber)/\(totalBlocks)" let isLocked = try await getBlockLockStatus(from: tag, block: blockNumber) if isLocked { print("Block \(blockNumber) is locked, skipping...") blockNumber += 1 try await writeNextBlock() return } let blankData = Data(repeating: 0x00, count: blockSize) try await write(data: blankData, to: tag, at: blockNumber) blockNumber += 1 try await writeNextBlock() } else { alertMessage = "Tag erased successfully!" } }
3. 请求标志位兼容性问题
.highDataRate标志可能导致部分标签兼容性差,可尝试使用默认速率:
try await tag.writeSingleBlock(requestFlags: [], blockNumber: block, dataBlock: data)
4. Session生命周期与连接校验
连接后需确认标签可用状态,避免无效操作:
Task { do { try await session.connect(to: currentTag) guard currentTag.isAvailable else { throw NSError(domain: "TagError", code: -1, userInfo: [NSLocalizedDescriptionKey: "Tag unavailable after connection"]) } print("Connected: ========\(currentTag.isAvailable)========") try await erase(tag: iso15693Tag) session.alertMessage = "Erase completed" session.invalidate() } catch { print("❗️", error) session.invalidate(errorMessage: error.localizedDescription) } }
额外优化与注意事项
- 批量写入减少通信次数:iCode Slix2支持多块写入,可减少指令发送频次提升稳定性:
func writeMultipleBlocks(data: [Data], to tag: NFCISO15693Tag, startingBlock: UInt8) async throws { try await tag.writeMultipleBlocks(requestFlags: [], startBlockNumber: startingBlock, dataBlocks: data) try await Task.sleep(nanoseconds: 100_000_000) } // 批量处理擦除逻辑 func erase(tag: NFCISO15693Tag) async throws { print("🏷️", "ERASING TAG") alertMessage = "ERASING TAG..." let sysInfo = try await getSystemInfo(from: tag) let totalBlocks = sysInfo.totalBlocks - 1 let blockSize = sysInfo.blockSize var currentBlock: UInt8 = 0 let batchSize: UInt8 = 4 while currentBlock < totalBlocks { let endBlock = min(currentBlock + batchSize - 1, totalBlocks) alertMessage = "ERASING TAG \(currentBlock)/\(totalBlocks)" var batchData = [Data]() var skipBatch = false for block in currentBlock...endBlock { let isLocked = try await getBlockLockStatus(from: tag, block: block) if isLocked { print("Block \(block) is locked, skipping batch...") skipBatch = true break } batchData.append(Data(repeating: 0x00, count: blockSize)) } if !skipBatch && !batchData.isEmpty { try await writeMultipleBlocks(data: batchData, to: tag, startingBlock: currentBlock) } currentBlock = endBlock + 1 } alertMessage = "Tag erased successfully!" }
- 权限与设备要求:确保
Info.plist配置NFCReaderUsageDescription,且设备运行iOS 13及以上版本。 - 操作引导:提示用户将iPhone NFC感应区(顶部)对准标签中心,保持稳定直至操作完成。
ISO15693错误码查询方式
ISO15693错误码的官方定义可通过目标标签的数据手册查询,iCode Slix2手册中会明确每个错误码的触发原因;也可参考ISO 15693-3标准文档,其中规定了通用响应错误码的含义。
内容的提问来源于stack exchange,提问作者Darren
相关产品推荐
相关产品推荐

