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.



