NFC Tag Reader Prototype

Overview

Building an NFC Tag-Reader App

Read NFC tags with NDEF messages in your app.

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 then stores the messages so the user can view them later.

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 entitlements 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

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 property. 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, the user taps the Scan button again.

@IBAction func beginScanning(_ sender: Any) {
    guard NFCNDEFReaderSession.readingAvailable else {
        let alertController = UIAlertController(
            title: "Scanning Not Supported",
            message: "This device doesn't support tag scanning.",
            preferredStyle: .alert
        )
        alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
        self.present(alertController, animated: true, completion: nil)
        return
    }

    session = NFCNDEFReaderSession(delegate: self, queue: nil, invalidateAfterFirstRead: false)
    session?.alertMessage = "Hold your iPhone near the item to learn more about it."
    session?.begin()
}

View in Source

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 the session or encountering an error
class MessagesTableViewController: UITableViewController, NFCNDEFReaderSessionDelegate {

View in Source

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()
    }
}

View in Source

Handle an Invalid Reader Session

When a reader session ends, it calls the delegate method readerSession(_:didInvalidateWithError:) and passes in an error object that gives the reason for ending the session. 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
        // successful read during a single-tag read session, or because the
        // user canceled a multiple-tag read 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)
            }
        }
    }

    // To read new tags, a new session instance is required.
    self.session = nil
}

View in Source

Write an NDEF Message

To write to a tag, the sample app starts a new reader session. This session must be active to write an NDEF message to the tag, so this time, invalidateAfterFirstRead is set to false, preventing the session from becoming invalid after reading the tag.

@IBAction func beginWrite(_ sender: Any) {
    session = NFCNDEFReaderSession(delegate: self, queue: nil, invalidateAfterFirstRead: false)
    session?.alertMessage = "Hold your iPhone near an NDEF tag to write the message."
    session?.begin()
}

View in Source

When the reader session detects a tag, it calls the readerSession(_:didDetectNDEFs:) delegate method. However, because the session doesn't become invalid after reading the first tag, it's possible for the session to detect more than one tag. The sample app writes to one tag only, so it checks that the session detected only one tag. If the session detected more than one, the app asks the user to remove the tags, and then restarts polling to scan for a new tag.

After the app confirms that it has only one tag, it connects to the tag and verifies that it's writable. The app then writes the NDEF message it read earlier to the tag.

func readerSession(_ session: NFCNDEFReaderSession, didDetect tags: [NFCNDEFTag]) {
    if tags.count > 1 {
        // Restart polling in 500 milliseconds.
        let retryInterval = DispatchTimeInterval.milliseconds(500)
        session.alertMessage = "More than 1 tag is detected. Please remove all tags and try again."
        DispatchQueue.global().asyncAfter(deadline: .now() + retryInterval, execute: {
            session.restartPolling()
        })
        return
    }
    
    // Connect to the found tag and write an NDEF message to it.
    let tag = tags.first!
    session.connect(to: tag, completionHandler: { (error: Error?) in
        if nil != error {
            session.alertMessage = "Unable to connect to tag."
            session.invalidate()
            return
        }
        
        tag.queryNDEFStatus(completionHandler: { (ndefStatus: NFCNDEFStatus, capacity: Int, error: Error?) in
            guard error == nil else {
                session.alertMessage = "Unable to query the NDEF status of tag."
                session.invalidate()
                return
            }

            switch ndefStatus {
            case .notSupported:
                session.alertMessage = "Tag is not NDEF compliant."
                session.invalidate()
            case .readOnly:
                session.alertMessage = "Tag is read only."
                session.invalidate()
            case .readWrite:
                tag.writeNDEF(self.message, completionHandler: { (error: Error?) in
                    if nil != error {
                        session.alertMessage = "Write NDEF message fail: \(error!)"
                    } else {
                        session.alertMessage = "Write NDEF message successful."
                    }
                    session.invalidate()
                })
            @unknown default:
                session.alertMessage = "Unknown NDEF tag status."
                session.invalidate()
            }
        })
    })
}

View in Source

Support Background Tag Reading

To learn how to set up your app to process tags that iOS reads in the background, see Adding Support for Background Tag Reading.

You might also like...
A prototype of custom tab bar using SwiftUI with techniques of mask + matchedGeometryEffect
A prototype of custom tab bar using SwiftUI with techniques of mask + matchedGeometryEffect

SliderTabBar A prototype of custom tab bar using SwiftUI with techniques of mask

A rapid prototype of UISwitch built with Swift and PaintCode.
A rapid prototype of UISwitch built with Swift and PaintCode.

LTJelloSwitch A cute UISwitch prototype built in about 8 hours. One of my co-worker gave me this concept last year. It was written in Objective-C and

Simple and highly customizable iOS tag list view, in Swift.
Simple and highly customizable iOS tag list view, in Swift.

TagListView Simple and highly customizable iOS tag list view, in Swift. Supports Storyboard, Auto Layout, and @IBDesignable. Usage The most convenient

Made in Swift - Tag layout for UICollectionView supporting 3 types of alignments - Left || Centre || Right
Made in Swift - Tag layout for UICollectionView supporting 3 types of alignments - Left || Centre || Right

TagCellLayout About Its an ui-collection-view LAYOUT class that takes care of all the logic behind making tags like layout using UICollectionView. It

Flow layout / tag cloud / collection view in SwiftUI.
Flow layout / tag cloud / collection view in SwiftUI.

SwiftUIFlowLayout A Flow Layout is a container that orders its views sequentially, breaking into a new "line" according to the available width of the

Creating a simple selectable tag view in SwiftUI is quite a challenge. here is a simple & elegant example of it.
Creating a simple selectable tag view in SwiftUI is quite a challenge. here is a simple & elegant example of it.

SwiftUI TagView Creating a simple selectable tag view in SwiftUI is quite a challenge. here is a simple & elegant example of it. Usage: Just copy the

When you scan the clothing tag, a 3D character appears and informs you of the clothing information.
When you scan the clothing tag, a 3D character appears and informs you of the clothing information.

1. Introduction When you scan the clothing tag, a 3D character appears and tells you the information on the clothes. You can select necessary informat

Made in Swift - Tag layout for UICollectionView supporting 3 types of alignments - Left || Centre || Right
Made in Swift - Tag layout for UICollectionView supporting 3 types of alignments - Left || Centre || Right

TagCellLayout About Its an ui-collection-view LAYOUT class that takes care of all the logic behind making tags like layout using UICollectionView. It

Simple and highly customizable iOS tag list view, in Swift.
Simple and highly customizable iOS tag list view, in Swift.

TagListView Simple and highly customizable iOS tag list view, in Swift. Supports Storyboard, Auto Layout, and @IBDesignable. Usage The most convenient

Highly customizable iOS tags view [input, edit, dynamic, tag, token, field, NSTokenField]
Highly customizable iOS tags view [input, edit, dynamic, tag, token, field, NSTokenField]

RKTagsView Highly customizable iOS tags view (like NSTokenField). Supports horizontal and vertical direction, editing, multiple selection, Auto Layout

Simple and highly customizable iOS tag list view, in Swift.
Simple and highly customizable iOS tag list view, in Swift.

TagListView Simple and highly customizable iOS tag list view, in Swift. Supports Storyboard, Auto Layout, and @IBDesignable. Usage The most convenient

Real-time communication application form Google Jacquard tag to macOS
Real-time communication application form Google Jacquard tag to macOS

Jacquard RTC Real-time communication application form Google Jacquard tag to macOS Abstract Want to use your Google Jacquard equipped product with you

TagKit makes it easy to create tag-based apps in SwiftUI.
TagKit makes it easy to create tag-based apps in SwiftUI.

About TagKit TagKit makes it easy to work with tags in Swift and SwiftUI. The result can look like this or completely different: Tags and tag views ca

Simple QRCode reader in Swift
Simple QRCode reader in Swift

QRCodeReader.swift is a simple code reader (initially only QRCode) for iOS in Swift. It is based on the AVFoundation framework from Apple in order to

A credit card reader and parser for iOS Using Native Vision/VisionKit

card-reader-ios A credit card reader and parser for iOS Using Native Vision/VisionKit May-14-2021.00-43-17.mp4 Instructions Hold camera up to a card a

Simple QRCode reader in Swift
Simple QRCode reader in Swift

QRCodeReader.swift is a simple code reader (initially only QRCode) for iOS in Swift. It is based on the AVFoundation framework from Apple in order to

🏁 make QRcode and QRcode Reader Tutorial
🏁 make QRcode and QRcode Reader Tutorial

QRCodeReaderTutorial-iOS 🏁 make QRcode and QRcode Reader Tutorial QR코드와 리더기를 만드는 오픈 라이브러리가 있지만 자체 라이브러리를 활용해서 만들어보기로 했다. 목차 QR코드 만들기 QR코드 Reader 만들기

An iOS widget-based HN reader
An iOS widget-based HN reader

Benuse, an iOS widget-based HN reader Why did you build this app? There already exist some great native Hacker News clients for iOS. I would recommend

A Hacker News reader in Swift
A Hacker News reader in Swift

SwiftHN A Hacker News reader in Swift using the best features of both the language and iOS 8 latest API (well, that's the end goal) SwiftHN is now ava

Owner
Pranav Kasetti
Contract iOS Developer and Tech-preneur. StackOverflow: https://stackoverflow.com/users/4995828/pranav-kasetti
Pranav Kasetti
NFC Forum Well Known Type Data Parser for iOS11 and Core NFC

NFCNDEFParse NFC Forum Well Known Type Data Parser for iOS11 and Core NFC. Supports parsing of types: Text - NFCForum-TS-RTD_Text_1.0 2006-07-24 Uri -

Jari Kalinainen 14 Oct 21, 2022
A open source Swift app for iOS 13 that allows you to check your NFC transit card information. Written with SwiftUI.

ABANDONED Metrodroid, which TransitPal was heavily inspired by, now has its own fully functional iOS app! It should be in the App Store "soon". I stro

Robbie Trencheny 132 Jun 30, 2022
NFCMate - A NFC Companion built using Swift with CoreNFC Framework

NFCMate NFCMate NFCMate is a NFC app written in Swift for iOS devices. Moreover,

Navemics 7 Nov 21, 2022
AmiiboReader - Reading data from amiibo by using Core NFC

AmiiboReader Reading data from amiibo by using Core NFC NTAG215 Data Sheet https

Shinichiro Oba 7 Mar 24, 2022
Design and prototype customized UI, interaction, navigation, transition and animation for App Store ready Apps in Interface Builder with IBAnimatable.

Design and prototype customized UI, interaction, navigation, transition and animation for App Store ready Apps in Interface Builder with IBAnimatable.

IBAnimatable 8.6k Jan 2, 2023
SwiftUI MovieDB prototype app built with Xcode 11 Beta & macOS 10.15 Catalina

SwiftUI MovieDB iOS 13 App SwiftUI MovieDB prototype app built with Xcode 11 Beta & macOS 10.15 Catalina Requirements macOS 10.15 Catalina Xcode 11 Be

Alfian Losari 297 Dec 17, 2022
Prototype actor and async/await toolkit for Swift 5.5+

Prototype actor and async/await toolkit for Swift 5.5+

d-exclaimation 0 Feb 17, 2022
An experimental prototype calculator.

What is NumberPad NumberPad is an experimental prototype to explore how we write, visualize, and manipulate math equations. This post highlights some

Bridger Maxwell 87 Apr 25, 2022
This is an initial prototype of the UI for demoing purposes

Mirage Demo good luck - fiig This is the original demo prototype for Mirage (notice the old spelling "Miirage", I know ?? ). The project is built usin

Mirage 3 Dec 2, 2021
Intraveneous AR prototype for course project

An AR prototype for intravenous (IV) injection. For Julia Micallef and Matt Chan's project in CSCI 6520G This is a scripted wizard of oz prototype, wh

Matt Chan 0 Nov 25, 2021