Core NFC 初体验

随着 WWDC 2017 的落幕,一大批新的技术(像 ARKit、Core ML、Core NFC 等等……)开始逐渐为开发者所知。开发者们又有了新的玩具可以玩一阵子了~

这篇文章就单独拿 Core NFC 来说吧,毕竟它和我们的生活紧密相关。

注意:浏览本文中的部分图片需要科学上网。

这次苹果爸爸只开始开放了 NFC 的读取权限,所以想拿 iPhone 当公交卡的同学,可能又要伤心了。但是拿 iPhone 来当个读卡器什么的,还是能玩一玩的~

然鹅,只有那些拥有 iOS 11 系统的 iPhone 7/7P 的同学,才能拥有这些尊贵的特权。

NFC

这次放出的 Core NFC 可以说是非常的轻量了,使用起来简直不能再简单一点。上图是 WWDC 上苹果提供的技术细分图,可以说基本涵盖了所有的格式。可以实现检测 NFC 标签 (NFC tags) 并读取包含 NDEF(NFC Data Exchange Format) 的数据。

实现步骤

配置

  • 在开发者后台给你的 App ID 添加 NFC 读取权限。
step 1
  • 在 Info.plist 里添加如下信息,用来提示用户获取设备的 NFC 读取权限。
<key>NFCReaderUsageDescription</key>
<string>some description...</string>
  • 在 entitlements 文件里添加如下信息。
<key>com.apple.developer.nfc.readersession.formats</key>
    <array>
        <string>NDEF</string>
    </array>

代码实现

Objective-c

  • 导入 CoreNFC 头文件
#import <CoreNFC/CoreNFC.h>
  • 设置代理
@interface YourViewController : UIViewController <NFCNDEFReaderSessionDelegate>
  • 在 .m 中实现如下代码
- (void)viewDidLoad {
    [super viewDidLoad];
    NFCNDEFReaderSession *session = [[NFCNDEFReaderSession alloc] initWithDelegate:self queue:dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT) invalidateAfterFirstRead:NO];
    [session beginSession];
}

- (void)readerSession:(nonnull NFCNDEFReaderSession *)session didDetectNDEFs:(nonnull NSArray<NFCNDEFMessage *> *)messages {
    for (NFCNDEFMessage *message in messages) {
        for (NFCNDEFPayload *payload in message.records) {
            NSLog(@"Payload data:%@",payload.payload);
        }
    }        
}

- (void)readerSession:(NFCNDEFReaderSession *)session didInvalidateWithError:(NSError *)error{
    NSLog(@"%@",error);
}

  • 你可以用如下方法停止 session
[session invalidateSession];

Swift

  • 导入 CoreNFC
import CoreNFC
  • 设置代理
class YourViewController: UIViewController, NFCNDEFReaderSessionDelegate
  • 实现如下代码
override func viewDidLoad() {
        super.viewDidLoad()

        let session = NFCNDEFReaderSession(delegate: self,
                      queue: DispatchQueue(label: "queueName", attributes: .concurrent), invalidateAfterFirstRead: false)
        session.begin()
    }

func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) {
    for message in messages {
    for record in message.records {
      print(record.payload)
    }
  }
}

func readerSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) {
        print(error.localizedDescription)
    }
  • 你可以用如下方法停止 session
session.invalidate()

注:每个 session 的扫描时间最多60s,如果超时需要再次开启 session。

以上,就是最简单的代码实现。

如果不出意外的话,编译并运行刚刚的代码,在 App 启动的时候,会出现如下场景...

launch

恭喜!你的第一个 NFC Demo 已经完成,快用你的卡片试一下吧!