The problem now, is that when you activate your NFCReader, it does not immediately return the tag...
...so you can not immediately assign reader.tagUID
To solve this, in NFCReader we can "Publish" the tagCode...
...and in the View, we show this published value.
Then, when NFCReader gets the tagCode, it will automatically update your SwiftUI View.
Try this:
import SwiftUI
import CoreNFC
struct ContentView: View {
@StateObject private var reader = NFCReader()
var body: some View {
VStack{
Text(reader.tagUID)
Button {
reader.activate()
} label: {
Text("Scan")
.font(.title)
}.padding()
}
}
}
class NFCReader: NSObject, ObservableObject, NFCTagReaderSessionDelegate {
@Published var tagUID = "UID"
var session: NFCTagReaderSession?
func activate() {
self.session = NFCTagReaderSession(pollingOption: .iso14443, delegate: self)
self.session?.alertMessage = "Hold Your Phone Near the NFC Tag"
self.session?.begin()
}
func tagReaderSessionDidBecomeActive(_ session: NFCTagReaderSession) {
print("Session Begun!")
}
func tagReaderSession(_ session: NFCTagReaderSession, didInvalidateWithError error: Error) {
print("Error with Launching Session")
}
func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) {
print("Connecting To Tag")
if tags.count > 1{
session.alertMessage = "More Than One Tag Detected, Please try again"
session.invalidate()
}
let tag = tags.first!
session.connect(to: tag) { [self] (error) in
if nil != error{
session.invalidate(errorMessage: "Connection Failed")
}
if case let .miFare(sTag) = tag{
let UID = sTag.identifier.map{ String(format: "%.2hhx", $0)}.joined()
print("UID: \(UID)")
print(sTag.identifier)
session.alertMessage = "UID Captured"
session.invalidate()
DispatchQueue.main.async {
self.tagUID = "\(UID)"
}
}
}
}
}