如何在 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()
}
}
我需要向我的 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()
}
}