Read NFC tag in SwiftUI

One of the technologies often discussed (sometimes for security reasons) is Near Field Communication (NFC). In this post, we’ll learn how to read information from an NFC tag. It’s possible to embed various types of data in a tag, such as contact information, a URL, WiFi credentials, and more, which can significantly enhance your application’s functionality.

In this example, we’ll assume that the tag contains a simple string: “Hello tag.”

To begin, once you create a project, you need to add the Near Field Communication capability. In your code, you must also import CoreNFC. After that in the info add the permission “Privacy – NFC Scan Usage Description”, if you omit this, your app will crash and you became crazy to understand the reason.

Now, let’s take a look at the main part, the NFCReader. Start by creating a file named NFCReader.swift:

import Foundation
import CoreNFC

@Observable
public class NFCReader: NSObject, NFCNDEFReaderSessionDelegate {
    public var startAlert = "Hold your iPhone near the tag."
    public var raw = "Raw Data will be available after scan."
    public var session: NFCNDEFReaderSession?
    
    public func read() {
        guard NFCNDEFReaderSession.readingAvailable else {
            print("Error")
            return
        }
        session = NFCNDEFReaderSession(delegate: self, queue: nil, invalidateAfterFirstRead: true)
        session?.alertMessage = self.startAlert
        session?.begin()
    }
    
    public func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) {
        DispatchQueue.main.async {
            if messages.count > 0, let dataMessage = String(data: messages[0].records[0].payload, encoding:.utf8) {
                self.raw = dataMessage
            }
            //session.invalidate()
        }
    }
    
    public func readerSessionDidBecomeActive(_ session: NFCNDEFReaderSession) {
    }
    
    public func readerSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) {
        print("Session did invalidate with error: \(error)")
        self.session = nil
    }
}

The NFCReader is marked with the Observable annotation, introduced in iOS 17. This feature allows SwiftUI to easily detect changes occurring within this class.

The startAlert is the message that appears when the sheet prompting the user to move the tag near the phone is displayed. The variable raw will contain the string read from the tag.

The NFCNDEFReaderSession is the session used to read the tag. Note the invalidateAfterFirstRead parameter in the constructor; if set to true, the sheet displayed for reading the tag automatically disappears once the tag is read (otherwise, we must call session.invalidate(), see the commented code).

When the tag is read, the readSession function is called. In this case, we retrieve the information from the first record on the tag (there could be more than one), and get the payload. It is also possible to obtain the type of the information, the typeInformationFormat, and the tag identifier (as an exercise, I suggest displaying these pieces of information).

Finally, in the ContentView we have:

import SwiftUI
import CoreNFC

struct ContentView: View {
    @State var NFCR = NFCReader()
    
    var body: some View {
        VStack(spacing: 10) {
            Text("NFC data: \(NFCR.raw)")
            Button("Read NFC") {
                NFCR.read()
            }
        }
    }
}

Thus, we create the NFCReader as State so we can get the changes, tapping on the button start to read, if the things are good, the string read is displayed.

The code https://github.com/niqt/NfcExample/tree/main

Note: English is not my native language, so I apologize for any errors. I use AI solely to generate the banner of the post; the content is human-generated.

To subscribe to my newsletter [https://nicoladefilippo.com/#mailinglist]

share this post with friends

Picture of Nicola De filippo

Nicola De filippo

I'm a software engineer who adds to the passion for technologies the wisdom and the experience without losing the wonder for the world. I love to create new projects and to help people and teams to improve

Leave a comment

Your email address will not be published. Required fields are marked *

Who I am

I'm a software engineer who adds to the passion for technologies the wisdom and the experience without losing the wonder for the world. I love to create new projects and to help people and teams to improve.

Follow Me Here

Get The Latest Updates

Periodically receive my super contents on coding and programming

join the family;)

Recent Posts