Sample Code

Building an NFC Tag Reader App

Use Core NFC to read tags with NDEF messages in your app.

Download

Overview

This sample code project shows how to use Core NFC in an app to read Near Field Communication (NFC) tags of types 1 through 5 that contains NFC Data Exchange Format (NDEF) data. To use this sample, download the project and build it using Xcode. Run the sample app on your iPhone. Tap the Scan button to start scanning for tags, then hold the phone near an NFC tag.

To read a tag, the sample app creates an NFC NDEF reader session and provides a delegate. The running reader session polls for NFC tags and calls the delegate when it finds tags that contain NDEF messages, passing the messages to the delegate. The delegate can read the messages and handle conditions that can cause a session to become invalid.

Configure the App to Detect NFC Tags

Begin building your tag reader by configuring your app to detect NFC tags. Turn on Near Field Communication Tag Reading under the Capabilities tab for the project’s target (see Add a capability to a target). This step:

  • Adds the NFC tag reading feature to the App ID.

  • Adds the NFC entitlement to the entitlement file.

Next, add the NFCReaderUsageDescription key as a string item to the Info.plist file. For the value, enter a string that describes the reason the app needs access to the device’s NFC reader. If the app attempts to read a tag without providing this key and string, the app exits.

Start a Reader Session

To start a reader session, create an NFCNDEFReaderSession object by calling the init(delegate:queue:invalidateAfterFirstRead:) initializer method and passing in:

  • The reader session delegate object.

  • The dispatch queue to use when calling methods on the delegate.

  • The invalidateAfterFirstRead flag to determine whether the reader session reads only a single tag or multiple tags.

After creating the reader session, give instructions to the user by setting the alertMessage. For example, you might tell users, “Hold your iPhone near the item to learn more about it.” The system displays this message to the user while the phone is scanning for NFC tags. Finally, call begin() to start the reader session. This enables radio-frequency polling on the phone, and the phone begins scanning for tags.

The sample app starts a reader session when the user taps the Scan button. The app configures the reader session to invalidate the session after reading the first tag. To read additional tags using the sample app, the user taps the Scan button again.

@IBAction func beginScanning(_ sender: Any) {
    session = NFCNDEFReaderSession(delegate: self, queue: nil, invalidateAfterFirstRead: true)
    session?.alertMessage = "Hold your iPhone near the item to learn more about it."
    session?.begin()
}

Adopt the Reader Session Delegate Protocol

The reader session requires a delegate object that conforms to the NFCNDEFReaderSessionDelegate protocol. Adopting this protocol allows the delegate to receive notifications from the reader session when it:

  • Reads an NDEF message

  • Becomes invalid due to ending or encountering an error

class MessagesTableViewController: UITableViewController, NFCNDEFReaderSessionDelegate {

Read an NDEF Message

Each time the reader session retrieves a new NDEF message, the session sends the message to the delegate by calling the readerSession(_:didDetectNDEFs:) method. This is the app’s opportunity to do something useful with the data. For instance, the sample app stores the message so the user can view it later.

func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) {
    DispatchQueue.main.async {
        // Process detected NFCNDEFMessage objects.
        self.detectedMessages.append(contentsOf: messages)
        self.tableView.reloadData()
    }
}

Handle an Invalid Reader Session

When a reader session terminates, the session calls the delegate method readerSession(_:didInvalidateWithError:) and passes in an error object that gives the reason for ending the session. The possible reasons include:

In the sample app, the delegate displays an alert when the reader session ends for any reason other than reading the first tag during a single tag reader session or the user canceling the session. Also, you cannot reuse an invalidated reader session, so the sample app sets self.session to nil.

func readerSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) {
    // Check the invalidation reason from the returned error.
    if let readerError = error as? NFCReaderError {
        // Show an alert when the invalidation reason is not because of a success read
        // during a single tag read mode, or user canceled a multi-tag read mode session
        // from the UI or programmatically using the invalidate method call.
        if (readerError.code != .readerSessionInvalidationErrorFirstNDEFTagRead)
            && (readerError.code != .readerSessionInvalidationErrorUserCanceled) {
            let alertController = UIAlertController(
                title: "Session Invalidated",
                message: error.localizedDescription,
                preferredStyle: .alert
            )
            alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
            DispatchQueue.main.async {
                self.present(alertController, animated: true, completion: nil)
            }
        }
    }

    // A new session instance is required to read new tags.
    self.session = nil
}

Support Background Tag Reading

The sample app supports background tag reading. To learn more about how to set up your app to process tags that iOS reads in the background, see Adding Support for Background Tag Reading.

See Also

First Steps

Adding Support for Background Tag Reading

Allow users to scan NFC tags without an app using background tag reading.