如何在 Swift (iOS) 中发送多个 NFC ISO7816 APDU?

How to send multiple NFC ISO7816 APDUs in Swift (iOS)?

我需要向我的 iso 7816 nfc 标签发送多条(比如说 50 条)adpu 消息。

顺序需要是:发送 -> 接收响应 -> 做一些计算 -> 发送 -> 接收响应 -> 做一些计算 -> 发送 -> ...

我该怎么做?

此代码在“1”之前打印“2”,因此没有地方可以实现依赖于 response1 的计算:

    func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) {
        session.connect(to: tag) { (error1: Error?) in
        if nil != error1{
         session.invalidate(errorMessage: "Connection Failed")
        }
        if case let .iso7816(sTag) = tag{
            sTag.sendCommand(apdu: apdu1) { (data:Data, int1:UInt8, int2:UInt8, error:Error?) in
                if error != nil{
                    return
                }
                print("1")
            }
            print("2")
            sTag.sendCommand(apdu: apdu2) { (data:Data, int1:UInt8, int2:UInt8, error:Error?) in
                if error != nil{
                    return
                }
                // ...

此代码 有效 ,但在块中创建块。因此可能会发生堆栈溢出和 块中的块 可能不符合编码约定等:

    func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) {
        session.connect(to: tag) { (error1: Error?) in
        if nil != error1{
         session.invalidate(errorMessage: "Connection Failed")
        }
        if case let .iso7816(sTag) = tag{
            sTag.sendCommand(apdu: apdu1) { (data:Data, int1:UInt8, int2:UInt8, error:Error?) in
                if error != nil{
                    return
                }
                //create apdu2 depend on response1
                sTag.sendCommand(apdu: apdu2) { (data:Data, int1:UInt8, int2:UInt8, error:Error?) in
                    if error != nil{
                        print(error!)
                        return
                    }
                    //create apdu3 depend on response1 and response2
                    sTag.sendCommand(apdu: apdu3) { (data:Data, int1:UInt8, int2:UInt8, error:Error?) in
                        if error != nil{
                            print(error!)
                            return
                        }
                        // ...
        

是否有更好的选择或者这是唯一可行的解​​决方案?

我是用信号量做的,但还有更多的可能性,正如评论中提到的@Paulw11

func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) {
    session.connect(to: tag) { (error1: Error?) in
    if nil != error1{
     session.invalidate(errorMessage: "Connection Failed")
    }
    if case let .iso7816(sTag) = tag{
        DispatchQueue.global(qos: .background).async { //because semaphore.wait() shouldn't block main thread
            let semaphore = DispatchSemaphore(value: 0)
            let apdu1 = //...
            sendApdu(apdu: apdu1, semaphore: semaphore)
            semaphore.wait()
            sendApdu(apdu: apdu2, semaphore: semaphore)
            semaphore.wait()
            sendApdu(apdu: apdu3, semaphore: semaphore)
            semaphore.wait()
        }
    }
}

func sendApdu(apdu: NFCISO7816APDU, semaphore: DispatchSemaphore){
    sTag.sendCommand(apdu: apdu3) { (data:Data, int1:UInt8, int2:UInt8, error:Error?) in
        if error != nil{
            print(error!)
            return
        }
        //... analyse response, put next apdu to a class variable etc
        semaphore.signal()
    }
}