苹果的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都出来了。是时候验证一把了