上下文
我正在开发一个数字板游戏(与移动应用程序)。玩家可以通过扫描他们的徽章(其中包含UUID)与应用程序交互。
我的问题
我创建了一个NFCReader服务来读取NFC徽章中的数据。当我从这个服务调用scan()
方法时,NFC弹出窗口也会显示出来,当我把NFC放在我的手机上时,它会被取消。但是,当我在触发NFC检测之前在我的手机上重复使用NFC徽章的操作时,NFC弹出将按预期显示,但有时会显示,在读取数据后不会将其排除。
预期情况:
Bug situation (当我的徽章在扫描方法调用之前已经在我的手机上划过了):
NFCReader服务
class NFCReader: NSObject, NFCNDEFReaderSessionDelegate, ObservableObject {
static var instance = NFCReader()
var session: NFCNDEFReaderSession?
var onRecordCallBack: ((_ badgeId: String) -> Void)?
func scan(message: String, onRecord: @escaping (_ badgeId: String) -> Void) {
guard NFCReaderSession.readingAvailable else {
return
}
self.onRecordCallBack = onRecord
self.session = NFCNDEFReaderSession(delegate: self, queue: .main, invalidateAfterFirstRead: false)
self.session?.alertMessage = message
self.session?.begin()
}
func readerSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) {
if let readerError = error as? NFCReaderError {
print("Error NFC reader : \(readerError.localizedDescription)")
}
self.session = nil
}
func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) {
guard
let message = messages.first,
let record = message.records.first,
let badgeId = String(data: record.payload, encoding: .utf8) else {
return
}
if let onRecordCallBack = self.onRecordCallBack {
onRecordCallBack(badgeId)
}
self.session?.invalidate()
}
}
使用ViewModel时NFCReader
struct InGameTravelView: View {
@StateObject var viewModel = InGameTravelViewModel()
var body: some View {
VStack {
if viewModel.isScanning {
Text("Scan your badge")
.onAppear() {
self.viewModel.scan()
}.onTapGesture {
self.viewModel.scan()
}
ForEach(viewModel.pilots) { pilot in
Text("\(pilot.player.name) \(pilot.player.role.name)")
.onTapGesture {
viewModel.currentPilot = pilot
viewModel.isScanning = false
}
}
} else {
switch viewModel.currentPilot.player.role.slug {
case .GOOD :
GoodPilotActionView(pilot: $viewModel.currentPilot) { selectedMatePilot in
viewModel.onActionFinished(selectedMatePilot)
}
case .BAD :
BadPilotActionView(pilot: $viewModel.currentPilot) {
//
}
}
}
}.onAppear() {
viewModel.fetchData()
}
}
}
extension InGameTravelView {
class InGameTravelViewModel: ObservableObject {
@Published var pilots: [Pilot] = []
@Published var pilotsAlreadyPlayed: [Pilot] = []
@Published var isScanning = true
@Published var currentPilot = Pilot.fake()
func fetchData() {
/* Retrieve current round */
let round = GameManager.instance.state.currentRound
/* Retrieve pilots */
self.pilots = round.pilots
if let pilot = self.pilots.first {
self.currentPilot = pilot
}
}
func scan() {
NFCReader.instance.scan(message: "Scan your badge") { badgeId in
print("badgeId : \(badgeId)")
let round = GameManager.instance.state.currentRound
guard let pilot = round.getPilotByBadgeId(badgeId: badgeId) else {
return
}
self.currentPilot = pilot
self.isScanning = false
}
}
}
如您所见,我手动使NFC会话(self.session?.invalidate()
)失效,以尽可能快地隐藏弹出(以避免玩家自行执行)。
我想坚持的事实是,这个bug是随机发生的,。有时候,它可以像预期的那样工作(GIF 1),即使在触发扫描之前,警徽被取消了。
发布于 2022-06-21 07:26:40
我认为您应该检查是否发生了一些错误响应,但它们没有被捕获。因此,在终端中可以找到一些相关的日志。
https://stackoverflow.com/questions/71988189
复制相似问题