WWDC Quick Look 💓 By SwiftGGTeam
What's new in Core NFC

What's new in Core NFC

观看原视频

Highlight

iOS 14 让 Core NFC 的 tag API completion handler 采用 Result enum,并扩展 ISO15693 的大容量内存和安全操作支持,开发者处理 NFC 读写结果时能直接按成功或失败分支编写代码。

核心内容

NFC 的难点通常不在扫描动作本身,而在扫描之后的 App 流程。一个停车计费器、共享滑板车、充电桩或餐厅菜单贴上 NFC tag 后,用户希望拿 iPhone 一碰就进入正确页面。Core NFC 负责把实体对象上的 tag 读出来,再把数据交给 App。

在 iPhone 7 之后,App 可以启动最长 60 秒的 NFC 读取 session。到 iPhone XS 开始,如果屏幕点亮,并且 NFC Forum NDEF message 里包含 Universal Link,系统还能在后台读 tag,显示通知横幅。用户点横幅后,这条 NDEF message 会以 NSUserActivity 的形式进入 App 的 UIApplicationDelegate restoration handler。

这场 session 的重点落在两个开发细节上。第一,Core NFC 在 tag API 里采用 Swift 的 Result enum,把成功结果和错误结果放进同一个 completion handler 参数。第二,NFCISO15693Tag 获得 ISO15693 第三版规范里的增强能力,覆盖更大内存 tag 和安全操作。

这两个变化都面向真实设备调试。开发者不再需要从多个可选返回值里判断一次 tag 命令到底成功还是失败;处理 ISO7816、MIFARE 或 ISO15693 tag 时,也能把成功数据和错误路径分开写清楚。

详细内容

NDEF 与后台标签入口

01:17)Core NFC 的基础模型是一个最长 60 秒的读取 session。演讲明确提到,Core NFC 支持 NDEF reading and writing,也支持 ISO7816、FeliCa、MIFARE 和 ISO15693 等 native tag protocol。

NFC tag contains an NFC Forum NDEF message with a universal link
-> iPhone XS or later reads the tag in the background while the screen is on
-> the system shows a notification banner
-> the user taps the banner
-> the app receives the NDEF message as NSUserActivity via UIApplicationDelegate restorationHandler

关键点:

  • 后台读取要求 NDEF message 里包含 Universal Link。
  • 系统先展示通知横幅,用户点击后才把数据交给 App。
  • App 侧收到的是 NSUserActivity,入口在 UIApplicationDelegate 的 restoration handler。
  • 其他 native tag protocol 仍然通过 Core NFC 的 reader session 在 App 内处理。

Result enum 让 ISO7816 命令更清楚

02:48)iOS 14 之前,ISO7816 tag 的 send command completion handler 有四个参数,App 需要先检查可选的 error,再解析其他参数。iOS 14 的新签名返回 Result<NFCISO7816ResponseAPDU, Error>,成功时拿到 NFCISO7816ResponseAPDU,失败时拿到 Error

detectedTag.sendCommand(apdu: apdu) { (result: Result<NFCISO7816ResponseAPDU, Error>) in
   switch result {
   case .success(let responseAPDU):
      /// Handle NFCISO7816ResponseAPDU object.
   case .failure(let error):
      /// Handle Error object.
   }
}

关键点:

  • detectedTag.sendCommand(apdu: apdu) 把 APDU 命令发送给检测到的 ISO7816 tag。
  • completion handler 只接收一个 result,类型是 Result<NFCISO7816ResponseAPDU, Error>
  • .success(let responseAPDU) 对应成功读取 tag 后得到的响应对象。
  • .failure(let error) 对应命令失败后的错误对象。
  • switch result 让成功路径和失败路径在代码结构上分开。

MIFARE 写入也改成 Result 处理

03:49)演讲用 WWDC 2019 的 NFCFishTag sample project 演示迁移:在 CouponViewController 的 write function 里,把 sendMiFareCommand 换成新的 Result 签名。成功分支处理返回的 data,错误分支处理 error。

// You need to zero-pad the data to fill the block size
if blockData.count < blockSize {
  blockData += Data(count: blockSize - blockData.count)
}

let writeCommand = Data([writeBlockCommand, offset]) + blockData
tag.sendMiFareCommand(commandPacket: writeCommand) { (response: Result<Data, Error>) in
  switch (response) {
  case .success(let responseData):
    if responseData[0] != successCode {
      self.readerSession?.invalidate(errorMessage: "Write tag error. Please try again.")
      return
    }

    let newSize = data.count - blockSize
    if newSize > 0 {
      self.write(data.suffix(newSize), to: tag, offset: (offset + 1))
    } else {
      self.readerSession?.invalidate()
    }
  case .failure(let error):
    let message = "Write tag error: \(error.localizedDescription). Please try again."
    self.readerSession?.invalidate(errorMessage: message)
  }
}

关键点:

  • 写入前先把 blockData 补到 blockSize,这是官方片段里的第一步。
  • writeCommand 由写入命令、偏移量和当前 block 数据拼接而成。
  • sendMiFareCommand 的 completion handler 返回 Result<Data, Error>
  • .success(let responseData) 分支检查 responseData[0] 是否等于 successCode
  • 写入后还有剩余数据时,代码递归调用 self.write,并把 offset 加一。
  • .failure(let error) 分支把错误信息传给 readerSession?.invalidate(errorMessage:)

ISO15693 增强覆盖大容量与安全操作

04:37)Core NFC 在 NFCISO15693Tag 协议中加入 ISO15693 第三版 2019 规范定义的增强功能。演讲给出的用途很具体:更大内存大小的 tag,以及安全操作。

NFCISO15693Tag enhancements mentioned in the session:
- fast reading multiple blocks
- extended write multiple blocks
- authenticate
- key update
- challenge
- read buffer
- extended get multiple blocks security status
- extended fast read multiple blocks
- send request

关键点:

  • fast reading multiple blocksextended fast read multiple blocks 面向多 block 读取。
  • extended write multiple blocks 面向扩展写入。
  • authenticatekey updatechallenge 属于安全相关操作。
  • send request 是新的 generic send command,用来发送 App 自己需要的任意数据包。
  • 这一组能力只在演讲中以功能签名列表出现,文章不补写未提供的 Swift 方法签名。

核心启发

  • 做一个现场标签写入工具:给门店、展台或设备贴纸写入 NDEF URL。为什么值得做:session 和官方资源都指向从 iPhone 创建 NFC tag 的场景。怎么开始:使用 NFCNDEFReaderSession 处理 NDEF reading and writing,先写入一个 Universal Link,再用真实 iPhone 验证后台读取路径。

  • 把停车、租车或充电入口贴到实体设备上:让用户碰一下 tag 后进入支付或启动页面。为什么值得做:演讲把 parking meters、scooter rental 和 electric car charging station 列为 Core NFC 的典型场景。怎么开始:让 tag 的 NDEF message 包含 Universal Link,App 从 NSUserActivity 恢复具体设备或站点上下文。

  • 做 ISO15693 库存巡检或设备维护 App:用 iPhone 读取大容量 ISO15693 tag 上的状态数据。为什么值得做:iOS 14 增加的 ISO15693 增强功能覆盖多 block 读取、扩展写入和安全操作。怎么开始:用 NFCTagReaderSession 连接 ISO15693 tag,再按设备协议选择 fast read、extended write 或 authenticate。

  • 给老协议 tag 做调试面板:把 ISO7816、MIFARE、FeliCa 和 ISO15693 的命令响应记录下来。为什么值得做:Core NFC 支持这些 native tag protocol,iOS 14 的 Result 签名让错误路径更清楚。怎么开始:先接入官方 sendCommandsendMiFareCommand 片段,把 .success 的响应和 .failure 的错误分别写进日志。

关联 Session

评论

GitHub Issues · utterances