NFC 这个词已经并不陌生了,前一段时间北京地铁支持 NFC 支付一时成为霸占头条的热点。其实在 90 年代末到 2000 年初,二维码和 NFC 就已经相继诞生,因为二维码成本低廉,技术门槛相对较低,所以,二维码迅速抢占了移动支付的市场,但 NFC 的发展并未所以中止。在 Android 端的 NFC 发展已经很是迅猛了,惋惜 Apple 迟迟未开放接口,在今年的 WWDC 上,苹果宣布开放其 NFC 接口 CoreNFC, 这为之后 NFC 的应用提供了更多的可能。json
若是你对 NFC 这项技术还比较陌生,那么这里科普一下,NFC(Near Field Communication)近场通讯,当两个设备相互靠近时能进行信息交流。许多企业讲 NFC 芯片放到卡片里,用带有 NFC 芯片的卡片来授予权限将容许谁有权限,好比说进出入公司。Apple CoreNFC 目前支持的格式有限,NFC 数据交换格式或 NDEF(一般用于当今市场上的大多数平板电脑和手机),好比 Apple Pay 。swift
这里咱们经过一个简单的实例程序来演示怎么使用 CoreNFC,这个程序能够用来读取存储在卡片上 NDEF 格式的信息。数组
为此,我使用 Arduino Uno 与 Adafruit PN532 Shield 配对,将其发送到样品 NDEF 格式的卡上。 若是你不具有这些东西,或者根本不想在这样的硬件上投入时间和金钱,请尝试找一张带有信息的预格式化卡。 本文中,我不会演示 NFC 格式化以及如何把数据存储到 NDEF 卡 中。bash
打开 Xcode 9 建立一个简单的 Swift 工程。使用 Storyboard 建立简单的页面:session
ViewController 以下:app
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var messageLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func scanPressed(_ sender: Any) {
// this is our newly created IBAction
}
}
复制代码
咱们的 app 要使用 NFC 必须进行应用受权:前提是你得有一个有效 Apple id (交过保护费的). 进行应用程序受权和隐私设置,打开developer.apple.com。 登陆你的账户,建立一个证书 —— 注册一个新的 APP ID。应用说明应该要支持 NFC 点击下一步,确保你的确认页面以下图:async
而后再建立 provisioning profile :ide
这一步完成了,在咱们刚建立的项目中导入 证书和描述文件,完成以后呢,咱们还需进行 Info.plist 配置 Privacy:函数
至此,咱们的开始工做就完成了。👇咱们进入 coding 阶段。ui
要实现 NFC 功能,咱们得接入 Core NFC framework:
import CoreNFC
复制代码
目前为止,iOS模拟器还没有支持 CoreNFC。 这意味着如你尝试导入CoreNFC,会收到一条错误,表示没有名为 CoreNFC 的模块。 遇到这种状况,请选择你的 iPhone 或 Generic iOS Device。接下来咱们实现 NFCNDEFReaderSessionDelegate 协议:
import UIKit
import CoreNFC
class ViewController: UIViewController, NFCNDEFReaderSessionDelegate {
@IBOutlet weak var messageLabel: UILabel!
var nfcSession: NFCNDEFReaderSession?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func scanPressed(_ sender: Any) {
}
func readerSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) {
print("The session was invalidated: \(error.localizedDescription)")
}
func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) {
// Parse the card's information
}
}
复制代码
其中两个 readerSession 函数会分别告诉咱们 NFC 会话成功或失败,成功后则返回 NFCNDEFMessage 格式的通讯数据,失败后会返回 error 信息。 固然,咱们首先还须要初始化 NFCNDEFReaderSession 并开启 NFC 监听。
@IBAction func scanPressed(_ sender: Any) {
nfcSession = NFCNDEFReaderSession.init(delegate: self, queue: nil, invalidateAfterFirstRead: true)
nfcSession?.begin()
}
复制代码
而后运行程序,看看:
若是提示 Session is invalidated unexpectedly ,那么请仔细核对 证书、描述文件以及 Privacy 设置是否正确。 这个过程并不难,简单几步就能搞定,下面咱们来看看怎么解析获取到的 message 。
首先,让咱们来看一下这个函数:
func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage])
复制代码
让咱们来看看每个 message 对象包含了哪些信息:
print(messages[0])
复制代码
咱们能够看到:
( // Payload one (There's only one payload in this card)
"TNF=1, /* Type Name Format */
Payload Type=<55>,
Payload ID=<>,
Payload=<0048656c 6c6f21>" /* What we're really interested in */
)
复制代码
根据打印的结果咱们能够看出: . messages 是一个 NFCNDEFMessages 对象的数组。 . NFCNDEFMessage 有一个 NFCNDEFPayload 对象数组 records 而后咱们再来看看每个 payload 又包含了哪些信息:
这里其实咱们只关心 payload 。好了,看看如何解析 records 吧。
func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) {
var result = ""
for payload in messages[0].records {
result += String.init(data: payload.payload.advanced(by: 3), encoding: .utf8)! // 1
}
DispatchQueue.main.async {
self.messageLabel.text = result
}
}
复制代码
来看看最终的效果: