In the previous post, we learned how to read an NFC tag. In this one, we’ll explore how to write to an NFC tag. As I mentioned in the previous post: ‘Once you create a project, you need to add the Near Field Communication capability. In your code, you must also import CoreNFC. After that, add the “Privacy – NFC Scan Usage Description” permission in the Info.plist file. If this is omitted, your app will crash, and you’ll be left confused about the reason.’
We want to write both text and a URL to the tag, so in ContentView
we have:
import SwiftUI import CoreNFC struct ContentView: View { @State var nfcWriter = NFCWriter() @State var textToWrite = "" @State var urlToWrite = "" var body: some View { VStack(spacing: 10) { TextField("Text to write", text: $textToWrite) TextField("Url to write", text: $urlToWrite) Button("Write NFC") { nfcWriter.write(url: urlToWrite, text: textToWrite) }.padding() }.padding() } }
We have two TextField
components to capture user input and a button that calls the write
function.
Now, let’s look at the main component, the writer. Create a file named NFCWriter
and copy the following code into it:
import Foundation import CoreNFC @Observable public class NFCWriter: NSObject, NFCNDEFReaderSessionDelegate { var startAlert = "Hold your iPhone near the tag." var session: NFCNDEFReaderSession? var urlToWrite = "https://www.nicoladefilippo.com" var textToWrite = "Hello World" public func write(url: String, text: String) { guard NFCNDEFReaderSession.readingAvailable else { print("Error") return } self.urlToWrite = url self.textToWrite = text session = NFCNDEFReaderSession(delegate: self, queue: nil, invalidateAfterFirstRead: false) session?.alertMessage = self.startAlert session?.begin() } public func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) { // Read logic } public func readerSession(_ session: NFCNDEFReaderSession, didDetect tags: [NFCNDEFTag]) { guard tags.count == 1 else { session.invalidate(errorMessage: "Cannot Write More Than One Tag in NFC") return } let currentTag = tags.first! session.connect(to: currentTag) { error in guard error == nil else { session.invalidate(errorMessage: "cound not connect to NFC card") return } currentTag.queryNDEFStatus { status, capacity, error in guard error == nil else { session.invalidate(errorMessage: "Write error") return } switch status { case .notSupported: session.invalidate(errorMessage: "Not Suported") case .readOnly: session.invalidate(errorMessage: "ReadOnly") case .readWrite: let textPayload = NFCNDEFPayload.wellKnownTypeTextPayload( string: self.textToWrite, locale: Locale.init(identifier: "en") )! let uriPayload = NFCNDEFPayload.wellKnownTypeURIPayload( url: URL(string: self.urlToWrite)! )! let messge = NFCNDEFMessage.init( records: [ uriPayload, textPayload ] ) currentTag.writeNDEF(messge) { error in if error != nil { session.invalidate(errorMessage: "Fail to write nfc card") } else { session.alertMessage = "Successfully writtern" session.invalidate() } } @unknown default: session.invalidate(errorMessage: "unknown error") } } } } public func readerSessionDidBecomeActive(_ session: NFCNDEFReaderSession) { } public func readerSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) { print("Session did invalidate with error: \(error)") self.session = nil } }
In the write
function, we initialize the session and the data we want to write. Note that in this case, invalidateAfterFirstRead
is set to false
because it can’t be true
when writing (otherwise, the session would immediately be invalidated).
The core of the functionality is the public func readerSession(_ session: NFCNDEFReaderSession, didDetect tags: [NFCNDEFTag])
function.
In this function, we check that only one tag is near the phone (since only one tag can be written to), then retrieve the tag and establish a connection to it. If everything checks out, we query it to verify its status. If writing is possible, we add an array of records containing a text and a URL (note how records are initialized differently based on the type). The capacity
property indicates the maximum NDEF message size, in bytes, that can be stored on the tag.
You should now be able to write to your tag.
The code https://github.com/niqt/WriteNfcTag
To subscribe to my newsletter [https://nicoladefilippo.com/#mailinglist]
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.