Core NFC在iOS 11中引入,用于处理NFC阅读Tag。由于目前只开放了读的权限,所以Core NFC是非常轻量级的一个框架。
![](https://img.haomeiwen.com/i4620094/df81ab665954492f.png)
上图是WWDC上苹果提供的NFC技术细分图,由于苹果支持所有格式的Tag,所以只需做大致了解即可。
使用NFC前需要注意一下几点:
- 需要开启一个session,与其他session类似,同时只能开启一个
- 需要App完全在前台模式(2018年以后发布的手机,支持后台调用NFC功能)
- 每个session最多扫描60s,超时需再次开启新session
- 配置读取单个或多个Tag,配置为单个时,会在读取到第一个Tag时自动结束session
- 隐私描述(后文会写到如何配置)会在扫描页面显示
使用NFC,第一步需要配置Capabilities,这会自动为你生成entitlements文件中的必要配置。同时为你的App ID激活相关功能。
![](https://img.haomeiwen.com/i4620094/bcae81cff0233013.png)
iOS 13之后的配置发生了更改。(如果你的APP是从低版本升级上来的需要添加新字段,否则上架AppStore会校验失败。)
Invalid entitlement for core nfc framework. The sdk version '13.0' and min OS version '9.0' are not compatible for the entitlement 'com.apple.developer.nfc.readersession.formats' because 'TAG is missing in the entitlement'.
![](https://img.haomeiwen.com/i4620094/897705d91d994f89.png)
第二步需要打开隐私相关设置,向info.plist中添加Privacy - NFC Scan Usage Description。
![](https://img.haomeiwen.com/i4620094/9a7534cef0a5dec2.png)
可以完全按照如下代码设置。此为读取标签的公共区域。
之后会提供读取UID的demo。
#import <CoreNFC/CoreNFC.h>
@interface ViewController ()<NFCNDEFReaderSessionDelegate>
@property (nonatomic ,strong)UIButton *beginButton;
@property (nonatomic ,strong)NFCNDEFReaderSession *session;
@property (nonatomic ,strong)UILabel *textLabel;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self createUI];
}
- (void)viewDidAppear:(BOOL)animated{
[self beginSession];
}
- (void)createUI{
[self.view addSubview:self.beginButton];
[self.view addSubview:self.textLabel];
}
- (void)viewDidDisappear:(BOOL)animated{
self.session = nil;
}
- (void)beginSession{
if (@available(iOS 11.0, *) && [NFCNDEFReaderSession readingAvailable]) {
self.session.alertMessage = NSLocalizedString(@"将标签放到手机背面", @"");
[self.session beginSession];
} else {
NSLog(NSLocalizedString(@"此设备不支持NFC", @""));
}
}
- (void)buttonAlick:(UIButton *)button{
if (button == self.beginButton) {
[self.session beginSession];
}
}
- (void)readerSession:(NFCNDEFReaderSession *)session didDetectNDEFs:(NSArray<NFCNDEFMessage *> *)messages API_AVAILABLE(ios(11.0)){
if (@available(iOS 11.0, *)) {
for (NFCNDEFMessage *message in messages) {
for (NFCNDEFPayload *payload in message.records) {
[self.session invalidateSession];
dispatch_async(dispatch_get_main_queue(), ^{
//在主线程里开启事件
NSString *nfcString = [[[NSString alloc] initWithData:payload.payload encoding:NSUTF8StringEncoding] substringFromIndex:1];//因为扫出来的数据多\^C 所以要截取所需要的字符串
self.textLabel.text = nfcString;
});
}
}
} else {
// Fallback on earlier versions
}
}
- (void)readerSession:(NFCNDEFReaderSession *)session didInvalidateWithError:(NSError *)error API_AVAILABLE(ios(11.0)){
self.session = nil;
}
- (NFCNDEFReaderSession *)session API_AVAILABLE(ios(11.0)){
if (!_session) {
_session = [[NFCNDEFReaderSession alloc] initWithDelegate:self queue:dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT) invalidateAfterFirstRead:NO];
}
return _session;
}
- (UIButton *)beginButton{
if (!_beginButton) {
_beginButton = [[UIButton alloc]initWithFrame:CGRectMake(100, 100, 200, 30)];
[_beginButton setTitle:NSLocalizedString(@"点击开始扫描标签", @"") forState:UIControlStateNormal];
_beginButton.titleLabel.font = [UIFont systemFontOfSize:17];
_beginButton.backgroundColor = [UIColor blueColor];
[_beginButton addTarget:self action:@selector(buttonAlick:) forControlEvents:UIControlEventTouchUpInside];
}
return _beginButton;
}
- (UILabel *)textLabel{
if (!_textLabel) {
_textLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 200, 200, 80)];
_textLabel.textColor = [UIColor whiteColor];
_textLabel.backgroundColor = [UIColor grayColor];
_textLabel.font = [UIFont systemFontOfSize:15];
_textLabel.numberOfLines = 0;
}
return _textLabel;
}
iOS 13以后注意:不可以设置其他协议方法
例如:
//此方法会在iOS13之后会屏蔽掉NFCNDEFReaderSessionDelegate 的协议方法。导致调用失败
- (void)readerSession:(NFCReaderSession *)session didDetectTags:(NSArray<__kindof id<NFCTag>> *)tags
网友评论