在 Swift 中以正确的格式在 NFC 标签上写入 URL

Write URL on NFC tag in correct format in Swift

我正在构建一个 NFC 读写应用程序。我用这段代码在标签上写 URLs:

private func writeTag(_ tag: NFCNDEFTag, for session: NFCReaderSession?) {
    guard let payload = "\u{02}en\(self.url ?? "")".data(using: .utf8) else {
        session!.invalidate()
        return
    }
    let record = NFCNDEFPayload(format: .nfcWellKnown, type: Data(), identifier: Data(), payload: payload)
    let myMessage = NFCNDEFMessage.init(records: [record])
    tag.writeNDEF(myMessage) { (error) in
        if error != nil {
            session?.invalidate(errorMessage: "Couldn't write tag")
        } else {
            session?.alertMessage = "Tag is written successfully"
            session!.invalidate()
        }
    }
}

文笔很好。但是,问题在于负载 (URL) 格式。例如,当我使用上面的代码将“https://github.com”写成 URL,然后使用另一个 NFC 应用程序读取我刚刚编写的内容时,我得到“enhttps:// github.co”。所以我确定问题出在这一行:

let payload = "\u{02}en\(self.url ?? "")".data(using: .utf8)

我试过将其更改为:

let payload = (self.url ?? "").data(using: .utf8)

然而,当我再次读取我刚刚从另一个应用程序写入的标签时,我得到的是“https://github.co”而不是“https://github.com”。

我应该如何将我的 URL 转换为数据以使其正常工作?

感谢任何帮助!

源代码位于:How To Make Your Swift App Work With NFC Tags in iOS 13

根据 Apple 的 NFCReaderSession 文档:

You do not create instances of this class. Instead, you create and use an instance of NFCNDEFReaderSession or NFCTagReaderSession. Only one reader session of any type can be active in the system at a time. The system puts additional sessions in a queue and processes them in FIFO order.

所以,我真的不确定您是如何创建 NFCReaderSession 的实例并调用 writeTag 的。但看起来,确实,您创建 payload 的方式是您的代码出了什么问题。

正确定义包含 URL 的负载:

let uriPayloadFromURL = NFCNDEFPayload.wellKnownTypeURIPayload(
           url: URL(string: "www.github.com")!
        )!

通过创建 NFCNDEFReaderSession 的实例并按如下方式实现 readerSession,您将获得您想要实现的目标。

func readerSession(_ session: NFCNDEFReaderSession, didDetect tags: [NFCNDEFTag]) {
    
    let uriPayloadFromURL = NFCNDEFPayload.wellKnownTypeURIPayload(
        url: URL(string: "www.github.com")!
    )!
    
    guard tags.count == 1 else {
        session.invalidate(errorMessage: "Can not write to more than one tag.")
        return
    }
    let currentTag = tags.first!
    
    session.connect(to: currentTag) { error in
        
        guard error == nil else {
            session.invalidate(errorMessage: "Could not connect to tag.")
            return
        }
        
        currentTag.queryNDEFStatus { status, capacity, error in
            guard error == nil else {
                session.invalidate(errorMessage: "Could not query status of tag.")
                return
            }
            
            switch status {
            case .notSupported: session.invalidate(errorMessage: "Tag is not supported.")
            case .readOnly:     session.invalidate(errorMessage: "Tag is only readable.")
            case .readWrite:
                let messge = NFCNDEFMessage.init(records: [uriPayloadFromURL])
                currentTag.writeNDEF(messge) { error in
                    if error != nil {
                        session.invalidate(errorMessage: "Failed to write message.")
                    } else {
                        session.alertMessage = "Successfully configured tag."
                        session.invalidate()
                    }
                }
                
            @unknown default:   session.invalidate(errorMessage: "Unknown status of tag.")
            }
        }
    }
}