I need to send multiple (lets say 50) adpu messages to my iso 7816 nfc tag.
The order needs to be: sending -> receiving response -> do some calculations -> sending -> receiving response -> do some calculations -> sending -> ...
How can I do it?
This code prints "2" before "1" so there is no place to implement response1-dependent calculations:
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
}
// ...
This code works, but creates blocks in blocks. So there can probably happen stack oveflow and blocks in blocks are probably not ok with coding conventions etc:
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
}
// ...
Are there better alternatives or is this the only functionable solution?
I made it with semaphores, but there are more possibilities as @Paulw11 mentioned in comments
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()
}
}