I have a Swift application that reads from an NFC card. I want it to show the data it read on the screen, which I am able to do if I have a button that checks for updated data using the getDetected()
function. I want to, however, update the view when it is done reading the NFC tag so I can immediately display the data. How can I do this?
NFC Reader class:
import Foundation
import CoreNFC
class NFCReader: NSObject, NFCNDEFReaderSessionDelegate {
var detected = [NFCNDEFMessage]()
var session: NFCNDEFReaderSession?
func beginScanning() {
guard NFCNDEFReaderSession.readingAvailable else { return }
session = NFCNDEFReaderSession(delegate: self, queue: nil, invalidateAfterFirstRead: true)
session?.alertMessage = "Hold your iPhone near the reader to unlock."
session?.begin()
}
func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) {
self.detected = messages
self.session = nil
}
func readerSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) {
self.session = nil
}
func getDetected() -> [NFCNDEFMessage] {
return detected
}
}
you could try the following approach, using a ObservableObject
.
Whenever the @Published var detected
is changed, the UI will be updated.
class NFCReader: NSObject, NFCNDEFReaderSessionDelegate, ObservableObject { // <--- here
@Published var detected = [NFCNDEFMessage]() // <--- here
var session: NFCNDEFReaderSession?
func beginScanning() {
guard NFCNDEFReaderSession.readingAvailable else { return }
session = NFCNDEFReaderSession(delegate: self, queue: nil, invalidateAfterFirstRead: true)
session?.alertMessage = "Hold your iPhone near the reader to unlock."
session?.begin()
}
func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) {
self.detected = messages
self.session = nil
}
func readerSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) {
self.session = nil
}
// no real need for this
func getDetected() -> [NFCNDEFMessage] {
return detected
}
}
struct ContentView: View {
@StateObject var readerNFC = NFCReader() // <-- here
var body: some View {
ForEach(readerNFC.detected, id: \.self) { msg in
// .....
}
}
}