Hey everyone! While working on an app which reads the Unique Identifiers of NFC tags I ran into a problem. When I run the code the phone is able to read the tag and add the UID into an array (I checked this by making it print the array whenever the array is updated) but I am unable to make the View update. The reason this is tricky is that when you press a button on the view, it activates the reader function reader.activate() which then updates the array in the Data class only if it successfully extracted the UID. How would I make the View reload every time a new UID is added to the array? Below is the code for the content view, Data class and then the NFC reader. Thanks! View:
struct ContentView: View {
@StateObject var data = Data()
let reader : NFCReader = NFCReader()
var body: some View {
NavigationView {
List {
Section(
header: Text("\(data.itemCount)" + " Items")
) { ForEach(data.products, id: \.self) {
product in Text(product)
}
.onDelete(perform: data.deleteItem)
.onMove(perform: data.moveItem)
}
}
.navigationTitle("My Products")
.navigationBarItems(leading: EditButton(), trailing: AddButton)
.navigationViewStyle(.stack)
}
.environmentObject(data)
}
var AddButton: some View {
Button(action: {
reader.activate()
// Next, once reader.activate() is done and sends data the tagUID, i need to open a new view with text imputs for name and description of product.
}, label: {
Image(systemName: "iphone.radiowaves.left.and.right")
})
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
// Do I need EnvironmentObject here???
.environmentObject(Data())
}
}
Data class:
//import Foundation
class Data: ObservableObject {
var tagCode = "UID"
@Published var products: [String] = []
@Published var itemCount = 0
func addItem() {
products.append(tagCode)
itemCount = itemCount + 1
print(tagCode + " Works!")
print(products)
}
func deleteItem(indexSet : IndexSet) {
products.remove(atOffsets: indexSet)
itemCount = itemCount - 1
}
func moveItem(indices : IndexSet, newOffset : Int) {
products.move(fromOffsets: indices, toOffset: newOffset)
}
}
NFC Reader:
import Foundation
import CoreNFC
import SwiftUI
class NFCReader: NSObject, ObservableObject, NFCTagReaderSessionDelegate {
var data : Data = Data()
private var tagUID = "UID"
private var session: NFCTagReaderSession?
func activate() {
self.session = NFCTagReaderSession(pollingOption: .iso14443, delegate: self)
self.session?.alertMessage = "Hold Your Phone Near 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)"
data.tagCode = "\(UID)"
data.addItem()
// add inputview change here
}
}
}
}
}