Unlocking the Potential of NFC in iOS Apps: A Comprehensive Guide to Reading and Writing NFC Tags

Raviraj Wadhwa
5 min readJan 22, 2024

--

Introduction:

In the rapidly advancing world of mobile technology, Near Field Communication (NFC) stands out as a powerful and versatile tool. This technology enables seamless communication between devices nearby, opening the door to a multitude of applications. In this blog post, we’ll explore the basics of NFC, delve into its real-world applications, and guide you through the process of implementing NFC functionality in your iOS app using Core NFC.

Understanding NFC:

NFC, Simplified: Near Field Communication (NFC) is a wireless communication technology that allows devices to exchange information when placed close together. Think of it as the magic behind contactless payments, secure access cards, and quick data transfers.

Applications of NFC:

  1. Contactless Payments: Conveniently make payments with a simple tap of your smartphone or card.
  2. Access Control: Securely access buildings, offices, or public transportation with NFC cards.
  3. Information Transfer: Effortlessly transfer data between devices, enhancing user experience.
  4. Smart Posters: Interact with posters or advertisements containing NFC tags for additional information.
  5. Healthcare: Utilize NFC for patient identification, medical equipment tracking, and secure access.

How to Use Core NFC in Your iOS App:

Now, let’s dive into a practical example of using Core NFC within a SwiftUI-based iOS app. In this example, we’ll create an app that can read and write contact information to and from NFC tags. The app will use the vCard format for simplicity.

Please note that NFC operations, reading and writing from and to NFC tags, require a physical iOS device with NFC capabilities. The iOS simulator does not support NFC functionalities. Also especially for writing NFC tags, you’ll need a physical NFC tag. NFC tags come in various forms, such as cards, stickers, or key fobs. These tags contain an NFC chip that can store data. You can purchase NFC tags online or from local electronics retailers.

Enable NFC Capabilities:

  • Enable the “Near Field Communication Tag Reading” capability in your Xcode project.

Creating a View:

  • Create a simple view with two buttons and a label.
  • A label is for displaying the read information from the NFC tag.
  • The two buttons are to begin reading and writing information from and into the NFC tag.
import SwiftUI
import CoreNFC

struct ContentView: View {
@State private var nfcContent = ""
@State private var isWriting = false

var body: some View {
VStack {
Text("NFC Content: \(nfcContent)")
.padding()

Button("Read NFC") {
startNFCReading()
}
.padding()

Button("Write NFC") {
startNFCWriting()
}
.padding()
.disabled(isWriting)
}
}

private func startNFCReading() {
let nfcSession = NFCNDEFReaderSession(
delegate: NFCReaderDelegate(
contentCallback: { content in
DispatchQueue.main.async {
self.nfcContent = content
self.isWriting = false
}
}
),
queue: nil,
invalidateAfterFirstRead: false
)
nfcSession.begin()
}

private func startNFCWriting() {
isWriting = true

let vCardPayload = """
BEGIN:VCARD
FN:John Doe
ORG:ABC Corporation
TEL:+123456789
EMAIL:john.doe@example.com
END:VCARD
"""

let nfcSession = NFCNDEFReaderSession(
delegate: NFCWriterDelegate(
content: vCardPayload
),
queue: nil,
invalidateAfterFirstRead: false
)
nfcSession.begin()
}
}

Conforming to read and write NFC delegates:

import CoreNFC

class NFCReaderDelegate: NSObject, NFCNDEFReaderSessionDelegate {
private var contentCallback: ((String) -> Void)?

init(contentCallback: @escaping (String) -> Void) {
self.contentCallback = contentCallback
}

func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) {
for message in messages {
for record in message.records {
if let payloadString = String(data: record.payload, encoding: .utf8) {
contentCallback?(payloadString)
}
}
}
}

func readerSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) {
print("Error reading NFC: \(error.localizedDescription)")
}
}

class NFCWriterDelegate: NSObject, NFCNDEFReaderSessionDelegate {
private let content: String

init(content: String) {
self.content = content
}

func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) {
// Writing is not implemented for reader, but this method is required
}

func readerSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) {
print("Error writing NFC: \(error.localizedDescription)")
}

func readerSessionDidBecomeActive(_ session: NFCNDEFReaderSession) {
// Implement writing functionality here if needed
print("Writing NFC...")
}
}

NFCReaderDelegate Class:

This class acts as a delegate for the NFCNDEFReaderSession, which is responsible for reading NFC tags. Here's what each part does:

Initializer (init):

  • The initializer takes a closure (contentCallback) as a parameter. This closure is a callback that will be called when NFC tags are successfully detected and their content is read.

readerSession(_:didDetectNDEFs:) Method:

  • This method is called when the NFC reader session detects NDEF (NFC Data Exchange Format) messages on a tag.
  • It iterates through each NDEF message and its records (individual pieces of data on the tag).
  • For each record, it attempts to convert the payload (the data on the tag) into a UTF-8 string (String(data:record.payload, encoding:.utf8)).
  • If the conversion is successful, it invokes the contentCallback closure, passing the payload string to it.

readerSession(_:didInvalidateWithError:) Method:

  • This method is called when the NFC reader session is invalidated, either due to an error or when the session is intentionally ended.
  • It prints an error message to the console if an error occurs during the NFC reading process.

NFCWriterDelegate Class:

This class acts as a delegate for the NFCNDEFReaderSession, which, in this example, is intended to be used for writing to NFC tags. Here's what each part does:

Initializer (init):

  • The initializer takes a content parameter, representing the content (payload) that will be written to the NFC tag.

readerSession(_:didDetectNDEFs:) Method:

  • This method is called when the NFC reader session detects NDEF messages on a tag.
  • It is intended for writing to NFC tags, but the writing functionality is not implemented in this example (hence the comment).
  • If writing functionality were implemented, it would be done within this method.

readerSession(_:didInvalidateWithError:) Method:

  • This method is called when the NFC reader session is invalidated, either due to an error or when the session is intentionally ended.
  • It prints an error message to the console if an error occurs during the NFC writing process.

readerSessionDidBecomeActive(_:) Method:

  • This method is called when the NFC reader session becomes active. It could be used to perform some tasks related to the writing process (not implemented in this example).
  • It prints a message to the console indicating that the NFC writing process is active.

Summary:

  • NFCReaderDelegate: Handles reading NFC tags, invokes a callback with the content when a tag is detected, and logs errors.
  • NFCWriterDelegate: Intended for writing to NFC tags (not fully implemented in this example), logs errors, and prints a message when the writing process becomes active.
  • These delegate classes are crucial for interacting with the Core NFC framework and responding to events during the NFC reading and writing processes.

In Conclusion:

Implementing NFC functionality in your SwiftUI-based iOS app opens doors to a multitude of possibilities. From simplifying interactions to securing access, Core NFC empowers your app with seamless connectivity.

Thank you for reading this guide! We hope it serves as a valuable resource as you explore the world of NFC in iOS development. If you have any questions or insights to share, feel free to connect. Happy coding! 🎉💻

--

--