iOS NFC — CoreNFC

Core NFC在iOS 11中引入,用于处理NFC阅读Tag。由于目前只开放了读的权限,所以Core NFC是非常轻量级的一个框架。


1688625-0962d5881300e923.png

上图是WWDC上苹果提供的NFC技术细分图,由于苹果支持所有格式的Tag,所以只需做大致了解即可。
使用NFC前需要注意一下几点:

  • 需要开启一个session,与其他session类似,同时只能开启一个
  • 需要App完全在前台模式(2018年以后发布的手机,支持后台调用NFC功能)
  • 每个session最多扫描60s,超时需再次开启新session
  • 配置读取单个或多个Tag,配置为单个时,会在读取到第一个Tag时自动结束session
  • 隐私描述(后文会写到如何配置)会在扫描页面显示

使用NFC,第一步需要配置Capabilities,这会自动为你生成entitlements文件中的必要配置。同时为你的App ID激活相关功能。

1688625-83d1b1d419bc66c1.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'.

image.png

第二步需要打开隐私相关设置,向info.plist中添加Privacy - NFC Scan Usage Description。

image.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


Demo:https://github.com/jiangkuoniu/NFC_DEMO.git

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 原文链接: http://fighting300.com... 大家可能听过NFC这项功能,或者有可能你每天都在使...
    fighting300阅读 10,093评论 10 8
  • 一、NFC简介 NFC(Near Field Communication,NFC)近场通信,是一种短距高频的无线电...
    张聪_2048阅读 22,242评论 8 42
  • 一、NFC简介 NFC(Near Field Communication,NFC)近场通信,是一种短距高频的无线电...
    nick5683阅读 10,354评论 0 4
  • 本篇文章共分为三个部分,读者可根据需要直接阅读对应部分: 1. iOS 对NFC支持的现状 2.NFC基本概念与相...
    Cstars阅读 13,975评论 3 9
  • Core NFC在iOS 11中引入,用于处理NFC阅读Tag。由于目前只开放了读的权限,所以Core NFC是非...
    李现科阅读 14,075评论 15 10