I'm building a NFC reading app. I want all my NFC implementation to be inside a separate class called NFCReader, so I can call it every time the user taps the readNFC button in my MainVC. Here is my current MainVC code:
class MainVC: ViewController {
@IBOutlet weak var readNFCButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
addTargetToReadNFCButton()
}
private func addTargetToReadNFCButton() {
readNFCButton.addTarget(self, action: #selector(readNFCButtonTouched), for: .touchUpInside)
}
@objc func readNFCButtonTouched() {
NFCReader().beginNFCReaderSession()
}
}
Here is my NFCReader class code:
class NFCReader: NSObject {
var session: NFCReaderSession?
func beginNFCReaderSession() {
session = NFCNDEFReaderSession(delegate: self, queue: nil, invalidateAfterFirstRead: true)
session!.alertMessage = "Hold your device near your tag for scanning"
session!.begin()
}
}
extension NFCReader: NFCNDEFReaderSessionDelegate {
func readerSessionDidBecomeActive(_ session: NFCNDEFReaderSession) {
print("readerSessionDidBecomeActive")
}
func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) {
print("didDetectTags")
}
func readerSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) {
print(error.localizedDescription)
}
}
The problem is that NFCReader's delegate functions are never being called. If I put the code from my NFCReader class into my MainVC class and call it directly, delegate functions are being called every time I scan my NFC tags. This code works:
class MainVC: ViewController {
@IBOutlet weak var readNFCButton: UIButton!
var session: NFCReaderSession?
override func viewDidLoad() {
super.viewDidLoad()
addTargetToReadNFCButton()
}
private func addTargetToReadNFCButton() {
readNFCButton.addTarget(self, action: #selector(readNFCButtonTouched), for: .touchUpInside)
}
@objc func readNFCButtonTouched() {
beginNFCReaderSession()
}
func beginNFCReaderSession() {
session = NFCNDEFReaderSession(delegate: self, queue: nil, invalidateAfterFirstRead: true)
session!.alertMessage = "Hold your device near your tag for scanning"
session!.begin()
}
}
extension MainVC: NFCNDEFReaderSessionDelegate {
func readerSessionDidBecomeActive(_ session: NFCNDEFReaderSession) {
print("readerSessionDidBecomeActive")
}
func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) {
print("didDetectTags")
}
func readerSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) {
print(error.localizedDescription)
}
}
Is there any way to make delegate functions work from my NFCReader class, not from MainVC? What's the mistake in my separate implementation?
Any help is appreciated!
EDITED:
I solved it by adding NFCReader property to main MainVC class:
let nfcReader = NFCReader()
And calling it like this:
@objc func readNFCButtonTouched() {
nfcReader.beginNFCReaderSession()
}
Thank you for your help!
Your NFCReader
is being initialized, and then almost immediately deinitialized because you didn’t store any references to it (which is necessary to keep the object alive).
You can confirm this by putting a breakpoint in the deinit
of your NFCReader
class