苹果的NFC功能之前一直仅支持读取,并且读取格式为type1到5的NDEF。
Your app can read tags to give users more information about their physical environment and the real-world objects in it. Using Core NFC, you can read Near Field Communication (NFC) tags of types 1 through 5 that contain data in the NFC Data Exchange Format (NDEF). For example, your app might give users information about products they find in a store or exhibits they visit in a museum.
自从苹果出了XS以后又开放了Adding Support for Background Tag Reading(背景标签读取),但是也仅仅支持以下几种格式 听闻iOS13将要开放读写功能,这一福音不知道又有多少人兴奋的睡不着觉。 所谓前人栽树,后人纳凉,在使用过程中也遇到几个问题,首先把代码贴出来 1.首先初始化session
guard NFCNDEFReaderSession.readingAvailable else { let alerView = UIAlertController( title: "Scanning Not Supported", message: "This device doesn't support tag scanning.", preferredStyle: .alert ) alerView.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) self.present(alerView, animated: true, completion: nil) return } // 此处表示我要识别iso15693和iso14443两种NFC标签类型 session = NFCTagReaderSession(pollingOption: [.iso15693, .iso14443], delegate: self) session?.alertMessage = "Hold your iPhone near the ISO15693 tag to begin transaction." session?.begin()2.实现协议与协议方法
class ViewController: UIViewController, NFCTagReaderSessionDelegate // MARK: - Delegate @available(iOS 13.0, *) func tagReaderSessionDidBecomeActive(_ session: NFCTagReaderSession) { print("tagReaderSessionDidBecomeActive") } @available(iOS 13.0, *) func tagReaderSession(_ session: NFCTagReaderSession, didInvalidateWithError error: Error) { print("tagReaderSession error:\(error)") } @available(iOS 13.0, *) func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) { print("tagReaderSession tags:\(tags)") }重点在tagReaderSession方法中,因为我识别了两种标签类型,所以我做了判断,发送指令之前一定需要先建立连接
@available(iOS 13.0, *) func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) { print("tagReaderSession tags:\(tags)") var tag: NFCTag? = nil var type: Int = 0 if case let .iso15693(fdTag) = tags.first { print("iso15693:\(self.string(from: fdTag.identifier))") tag = tags.first type = 1 } if case let .miFare(mifareTag) = tags.first { print("mifareTag:\(self.string(from: mifareTag.identifier))") if mifareTag.mifareFamily == .ultralight { tag = tags.first type = 2 } } if tag == nil { session.invalidate(errorMessage: "No valid tag found.") return } session.connect(to: tag!) { (error: Error?) in if error != nil { session.invalidate(errorMessage: "Connection error. Please try again.") return } print("connect tag:\(String(describing: tag))") if type == 1 { self.writeData(from: tag!) }else { self.readMifare(tag!) } } }剩下的就是发送命令了,中间做了很多命令测试,例如15693的writeSingleBlock、readSingleBlock、getSystemInfo等,包括两条命令的顺序更换等,举个例子 写:
func writeData(from tag: NFCTag) { print("*********") guard case let .iso15693(one_five_six_nine_three_tag) = tag else { print("-----") return } let fastRead: [UInt8] = [0x00, 0x00, 0x00] DispatchQueue.global().async { // self.write15693(Data(fastRead), from: one_five_six_nine_three_tag) one_five_six_nine_three_tag.customCommand(requestFlags: [.highDataRate], customCommandCode: 0xCF, customRequestParameters: Data(fastRead)) { (responseData, error) in print("responseData:\(responseData),error:\(String(describing: error))") } } }读(可以连续读取,因为标签需要两条命令之前间隔500ms所以我使用了延时):
func readMifare(_ tag: NFCTag) { guard case let .miFare(mifareTag) = tag else { return } DispatchQueue.global().async { // let ledCommand: [UInt8] = [0x40, 0xc9, 0x02, 0x00, 0x00, 0x00, 0x00] // let first: [UInt8] = [0x40, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00] let first: [UInt8] = [0x71, 0x07] mifareTag.sendMiFareCommand(commandPacket: Data(first)) { (responseData, error: Error?) in print("responseData:\([UInt8](responseData)), error:\(String(describing: error))") // DispatchQueue.global().asyncAfter(deadline: .now() + 0.5) { // let second: [UInt8] = [0x40, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00] // mifareTag.sendMiFareCommand(commandPacket: Data(second)) { (responseData, error: Error?) in // print("temperature:\(self.string(from: responseData)), error:\(String(describing: error))") // self.session?.invalidate() // } // } } } }中间遇到的问题: 1. -[NFCTagReaderSession _connectTag:error:] Error Domain=NFCError Code=100 “Stack Error” -[NFCTagReaderSession transceive:tagUpdate:error:] 解决方案:杀掉进程重新启动解决 2.15693错误 706 Error Domain=NFCError Code=2 “Missing required entitlement” (Error Domain=NFCError Code=2 “Missing required entitlement” UserInfo={NSLocalizedDescription=Missing required entitlement}") 当报这个错误的时候已经成功地称为readSingleBlock函数从标签读取改变 经过大量查找问题可能是Xcode Beta 3版本问题。参考与跟踪:CoreNFC:使用NFCISO15693Tag协议发送自定义命令 今天Xcode Beta 4与iOS 13 Beta 4都出来了。是时候验证一把了