iOS - getting both NFCTag hardware id and NDEF message in one reading session
Asked Answered
G

2

6

I'm currently facing a problem with implementing a specific feature into an NFC based iOS 13 app. When reading a tag, I'd like to get the unique hardware id and the NDEF message in one session. So far I've checked different sample projects, including code provided by Apple and was able to get the information I'm interested in, but not in the same reading session.

I simplified the following code snippets to better focus on the problem (missing error checks, etc.).

Using an NFCTagReaderSession to get the unique hardware id:

func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) {
    let tag = tags.first!

    session.connect(to: tag) { (error: Error?) in
        if case let .miFare(mifareTag) = tag {

            print(mifareTag.identifier as NSData) //this is the info I'm interested in

        }
    }
}

The payload type of a message record however seems to be only available in a NFCNDEFReaderSession:

func readerSession(_ session: NFCNDEFReaderSession, didDetect tags: [NFCNDEFTag]) {

        let tag = tags.first!
        session.connect(to: tag, completionHandler: { (error: Error?) in

            tag.queryNDEFStatus(completionHandler: { (ndefStatus: NFCNDEFStatus, capacity: Int, error: Error?) in


                tag.readNDEF(completionHandler: { (message: NFCNDEFMessage?, error: Error?) in
                    var statusMessage: String
                    if nil != error || nil == message {
                        statusMessage = "Fail to read NDEF from tag"
                    } else {
                        statusMessage = "Found 1 NDEF message"

                        let payload = message.records.first!

                        if let type = String(data: payload.type, encoding: .utf8) {
                            print("type:%@", type) //this is the info I'm interested in
                        }


                    }

                    session.alertMessage = statusMessage
                    session.invalidate()
                })
            })
        })
    }

As you can see, I can either get the hardware id, using a NFCTagReaderSession or the payload type of a message record, using a NFCNDEFReaderSession. Am I missing something here or are there indeed two different reading sessions required to get the information I'm interested in? Thanks in advance.

Gombach answered 16/10, 2019 at 7:20 Comment(2)
did you ever get this working? I am looking into a similar scenario where i want to be able to read the NDEF tag and then proceed to issue writes/reads using NFCTagReaderSessionHeadward
@Gombach I have the exact same issue. Did you find a solution for this?Swordtail
S
3

I finally found the solution for this :)

You can actually read the NDEF data in the delegate functions of your NFCTagReaderSession but in iOS 13 you have to use another delegate.

It seems in iOS 11 and 12 NFCTag was a protocol but in iOS 13 NFCTag became an enum and the former protocol was renamed to __NFCTag.

An __NFCTag can be casted to an NFCNDEFTag and then you can read NDEF data as usual.

To get an __NFCTag in your delegate functions you need to use __NFCTagReaderSessionDelegate instead.

To initialize your session you prepend __ to the pollingOption argument label of the initializer.

To connect to the tag you need to use __connect.

Here is how to read the identifier and the NDEF data.

func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [__NFCTag]) {
  let tag = tags.first!

  session.__connect(to: tag) { (error: Error?) in
    if let ndefTag = tag as? NFCNDEFTag {
      if let miFareTag = ndefTag as? NFCMiFareTag {
        // here you can get miFareTag.identifier like in your first code sample
      }
      
      ndefTag.readNDEF(completionHandler: { (message, error) in
        // here you can read NDEF data like in your second code sample
      })
    }
  }
}
Swordtail answered 8/9, 2020 at 7:6 Comment(1)
I tried this, the functions all seem to work but when I change ndefTag.readNDEF to WriteNDEF. I get a 401 stack error when writing the payload. My code can be found #64408423Marshamarshal
H
0

I had the same issue and found solution in Apple's sample project, which I hardly recommend to read.

FYI: Avoid using classes and methods with underscores as a prefix, it could lead you to the application rejection on AppStore.

Hectogram answered 13/5, 2022 at 12:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.