首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在读取数据后,NFC警报并不总是被解除。

在读取数据后,NFC警报并不总是被解除。
EN

Stack Overflow用户
提问于 2022-04-24 12:03:40
回答 1查看 76关注 0票数 0

上下文

我正在开发一个数字板游戏(与移动应用程序)。玩家可以通过扫描他们的徽章(其中包含UUID)与应用程序交互。

我的问题

我创建了一个NFCReader服务来读取NFC徽章中的数据。当我从这个服务调用scan()方法时,NFC弹出窗口也会显示出来,当我把NFC放在我的手机上时,它会被取消。但是,当我在触发NFC检测之前在我的手机上重复使用NFC徽章的操作时,NFC弹出将按预期显示,但有时会显示,在读取数据后不会将其排除。

预期情况

Bug situation (当我的徽章在扫描方法调用之前已经在我的手机上划过了):

NFCReader服务

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
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),即使在触发扫描之前,警徽被取消了。

EN

回答 1

Stack Overflow用户

发布于 2022-06-21 07:26:40

我认为您应该检查是否发生了一些错误响应,但它们没有被捕获。因此,在终端中可以找到一些相关的日志。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71988189

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档