You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

iOS13下无法读取电子护照NFC芯片,tagReaderSession未触发求助

解决iOS13下无法检测电子护照NFC芯片的问题

看起来你遇到的核心问题是使用了不适合的NFC会话类型,再加上权限配置的小疏漏,导致电子护照的检测方法从未被触发。我来一步步帮你梳理修复方案:

1. 替换为专门的ISO7816会话类型

电子护照是基于ISO7816标准的智能卡,iOS中针对这类卡片提供了NFCISO7816TagReaderSession,它比通用的NFCTagReaderSession更精准地适配这类设备的检测逻辑。通用会话对ISO7816卡片的支持有限,这也是你的didDetect方法没被调用的主要原因。

2. 修正Entitlements权限配置

你的授权文件里缺少了ISO7816格式的权限,需要把它添加到com.apple.developer.nfc.readersession.formats数组中,修改后的配置如下:

<key>com.apple.developer.nfc.readersession.formats</key>
<array>
    <string>NDEF</string>
    <string>TAG</string>
    <string>ISO7816</string>
</array>

3. 适配代码到ISO7816会话

把你的代码替换为适配NFCISO7816TagReaderSession的版本,包括代理协议和会话初始化:

import UIKit
import CoreNFC

class ViewController: UIViewController, NFCISO7816TagReaderSessionDelegate {
    var nfcSession: NFCISO7816TagReaderSession?
    
    func tagReaderSessionDidBecomeActive(_ session: NFCISO7816TagReaderSession) {
        print("Tag reader did become active")
        print("isReady: \(session.isReady)")
    }
    
    func tagReaderSession(_ session: NFCISO7816TagReaderSession, didInvalidateWithError error: Error) {
        print("Session error: \(error.localizedDescription)")
        nfcSession = nil
    }
    
    func tagReaderSession(_ session: NFCISO7816TagReaderSession, didDetect tags: [NFCISO7816Tag]) {
        // 现在这个方法应该能被触发了!
        guard let passportTag = tags.first else {
            // 如果没读到有效标签,重启轮询
            session.restartPolling()
            return
        }
        
        print("Detected ePassport tag: \(passportTag)")
        
        // 连接标签并发送SELECT AID指令(对应你的电子护照AID)
        session.connect(to: passportTag) { [weak self] connectError in
            guard connectError == nil else {
                print("Failed to connect to tag: \(connectError!)")
                session.invalidate()
                return
            }
            
            // 构造选择AID的APDU指令
            let selectAIDCommand = NFCISO7816APDU(
                instructionClass: 0x00,
                instructionCode: 0xA4,
                p1: 0x04,
                p2: 0x00,
                data: Data(hex: "A0000002471001"),
                expectedResponseLength: 0
            )
            
            passportTag.sendCommand(apdu: selectAIDCommand) { response, commandError in
                if let commandError = commandError {
                    print("Command failed: \(commandError)")
                    session.invalidate()
                    return
                }
                
                if let response = response {
                    print("Response data: \(response.data.hexString)")
                    print("Status word: \(String(format: "%04X", response.sw))")
                    // 这里可以继续处理电子护照的其他指令
                }
                
                session.invalidate()
            }
        }
    }
    
    @IBAction func clickedNFC(_ sender: Any) {
        // 先检查设备是否支持NFC读取
        guard NFCISO7816TagReaderSession.readingAvailable else {
            print("NFC reading is not available on this device")
            return
        }
        
        nfcSession = NFCISO7816TagReaderSession(pollingOption: .iso14443, delegate: self, queue: nil)
        nfcSession?.alertMessage = "Place the device on the inner cover of the passport"
        nfcSession?.begin()
    }
}

// 辅助扩展:方便处理十六进制数据
extension Data {
    init(hex: String) {
        self.init()
        let cleanedHex = hex.replacingOccurrences(of: " ", with: "")
        let hexChars = Array(cleanedHex)
        for i in stride(from: 0, to: hexChars.count, by: 2) {
            let byteString = String(hexChars[i...i+1])
            if let byte = UInt8(byteString, radix: 16) {
                append(byte)
            }
        }
    }
    
    var hexString: String {
        return map { String(format: "%02X", $0) }.joined()
    }
}

4. 额外注意事项

  • 必须用物理设备测试:iOS模拟器不支持NFC功能,一定要用iPhone 7及以上的真机。
  • 贴合位置要准确:电子护照的NFC芯片一般在护照内页的照片页附近,需要把设备紧贴芯片区域,避免中间有遮挡。
  • 权限配置要生效:修改Entitlements后,记得重新签名应用,确保权限正确加载。

内容的提问来源于stack exchange,提问作者Jan Moritz

火山引擎 最新活动