iOS开发-CoreNFC实现NFC标签Tag读取功能

iOS开发-CoreNFC实现NFC标签Tag读取功能

一、NFC近场通信

近场通信(NFC)是一种无线通信技术,它使设备能够在不使用互联网的情况下相互通信。它首先识别附近配备NFC的设备。NFC常用于智能手机和平板电脑。

二、实现NFC标签Tag读取功能

在iOS中提供了CoreNFC来实现NFC标签Tag读取功能。主要使用的类是NFCTagReaderSession。

NFCTagReaderSession配置读取器会话的RF轮询;可以将多个选项"或"运算在一起。此选项会影响可能的NFC标签类型。同时需要实现delegate来实现扫描的回调。

NFCTagReaderSession初始化

 if (@available(iOS 13.0, *)) {
        if (NFCNDEFReaderSession.readingAvailable) {
            self.tagSession = [[NFCTagReaderSession alloc]
                                initWithPollingOption:(NFCPollingISO14443 | NFCPollingISO15693 | NFCPollingISO15693) delegate:self queue:dispatch_get_main_queue()];
            self.tagSession.alertMessage = @"读取卡片,请将卡片靠近手机";
            [self.tagSession beginSession]; //开始识别 弹出识别提示框
        }else{
            NSLog(@"NFC功能只支持iphone7以及iOS13.0以上设备");
        }
    }else{
        NSLog(@"NFC功能只支持iphone7以及iOS13.0以上设备");
    }

NFCNDEFReaderSessionDelegate的相关方法

  • 识别结果的回调

-(void)readerSession:(NFCNDEFReaderSession *)session didDetectNDEFs:(NSArray<NFCNDEFMessage *> *)messages API_AVAILABLE(ios(11.0))

  • 错误回调

-(void)readerSession:(NFCNDEFReaderSession *)session didInvalidateWithError:(NSError *)error API_AVAILABLE(ios(11.0))

  • 在Session无效时调用
  • (void)tagReaderSession:(NFCTagReaderSession *)session didInvalidateWithError:(NSError *)error API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(watchos, macos, tvos)
  • 当NFC读取器会话变为Active时调用
  • (void)tagReaderSessionDidBecomeActive:(NFCTagReaderSession *)session API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(watchos, macos, tvos)
  • 当读取器在轮询序列中检测到NFC标记时调用
  • (void)tagReaderSession:(NFCTagReaderSession *)session didDetectTags:(NSArray<__kindof id> *)tags API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(watchos, macos, tvos)

实现识别NFC标签Tag完整代码如下

#import "INNFCExampleViewController.h"
#import <CoreNFC/CoreNFC.h>

API_AVAILABLE(ios(11.0))
@interface INNFCExampleViewController ()<NFCNDEFReaderSessionDelegate, NFCTagReaderSessionDelegate>

@property (nonatomic, strong) NFCNDEFReaderSession *session;

@property (nonatomic, strong) NFCTagReaderSession *tagSession;
 
@property (nonatomic, strong) id<NFCMiFareTag> currentTag;

@property (nonatomic, strong) UILabel *showLabel;

@end

@implementation INNFCExampleViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    self.view.backgroundColor = [UIColor whiteColor];
    
    UIButton *startQueryBtn;
    startQueryBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    startQueryBtn.frame = CGRectMake(50, 100, 60, 36);
    startQueryBtn.layer.cornerRadius = 4;
    startQueryBtn.backgroundColor = [UIColor brownColor];
    [startQueryBtn setTitle:@"开始识别" forState:UIControlStateNormal];
    [startQueryBtn addTarget:self action:@selector(startQueryBtnClick) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:startQueryBtn];
    
    UIButton *endQueryBtn;
    endQueryBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    endQueryBtn.frame = CGRectMake(250, 100, 60, 36);
    endQueryBtn.layer.cornerRadius = 4;
    endQueryBtn.backgroundColor = [UIColor brownColor];
    [endQueryBtn setTitle:@"结束识别" forState:UIControlStateNormal];
    [endQueryBtn addTarget:self action:@selector(endQueryBtnClick) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:endQueryBtn];
}

- (void)startQueryBtnClick {
    
    if (@available(iOS 13.0, *)) {
        if (NFCNDEFReaderSession.readingAvailable) {
            self.tagSession = [[NFCTagReaderSession alloc]
                                initWithPollingOption:(NFCPollingISO14443 | NFCPollingISO15693 | NFCPollingISO15693) delegate:self queue:dispatch_get_main_queue()];
            self.tagSession.alertMessage = @"读取卡片,请将卡片靠近手机";
            [self.tagSession beginSession]; //开始识别 弹出识别提示框
        }else{
            NSLog(@"NFC功能只支持iphone7以及iOS13.0以上设备");
        }
    }else{
        NSLog(@"NFC功能只支持iphone7以及iOS13.0以上设备");
    }
    
    /**
     //如果希望读取多个标签invalidateAfterFirstRead设置为NO
     if (@available(iOS 11.0, *)) {
         __weak typeof(self) weakSelf = self;
         self.session = [[NFCNDEFReaderSession alloc] initWithDelegate:weakSelf queue:dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT) invalidateAfterFirstRead:YES];
         [self.session beginSession];
     } else {
         // Fallback on earlier versions
     }
     */
}

- (void)endQueryBtnClick {
    
    /**
     if (@available(iOS 11.0, *)) {
         [self.session invalidateSession];
     } else {
         // Fallback on earlier versions
     }
     */
}

#pragma mark -- <NFCNDEFReaderSessionDelegate>

//扫描到的回调

-(void)readerSession:(NFCNDEFReaderSession *)session didDetectNDEFs:(NSArray<NFCNDEFMessage *> *)messages API_AVAILABLE(ios(11.0)){

    for (NFCNDEFMessage *message in messages) {
        for (NFCNDEFPayload *payload in message.records) {
            NSLog(@"readerSession payload data = %@", payload.payload);
            NSString *str = [[NSString alloc] initWithData:payload.payload encoding:NSUTF8StringEncoding];
            //回到主线程
            dispatch_async(dispatch_get_main_queue(), ^{
                NSLog(@"readerSession str:%@",str);
            });
        }
    }
}

//错误回调


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


#pragma mark -- NFCTagReaderSessionDelegate

/*!
 * @method tagReaderSession:didInvalidateWithError:
 *
 * @param session   The session object that is invalidated.
 * @param error     The error indicates the invalidation reason.
 *
 * @discussion      Gets called when a session becomes invalid.  At this point the client is expected to discard
 *                  the returned session object.
 */
- (void)tagReaderSession:(NFCTagReaderSession *)session didInvalidateWithError:(NSError *)error API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(watchos, macos, tvos) {
    NSLog(@"tagReaderSession didInvalidateWithError error:%@", error);
    if (error.code == 200) {
        return;
    }
    [session invalidateSession];
}

/*!
 * @method tagReaderSessionDidBecomeActive:
 *
 * @param session   The session object in the active state.
 *
 * @discussion      Gets called when the NFC reader session has become active. RF is enabled and reader is scanning for tags.
 *                  The @link readerSession:didDetectTags: @link/ will be called when a tag is detected.
 */
- (void)tagReaderSessionDidBecomeActive:(NFCTagReaderSession *)session API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(watchos, macos, tvos) {
    NSLog(@"tagReaderSession tagReaderSessionDidBecomeActive");
}

/*!
 * @method tagReaderSession:didDetectTags:
 *
 * @param session   The session object used for tag detection.
 * @param tags      Array of @link NFCTag @link/ objects.
 *
 * @discussion      Gets called when the reader detects NFC tag(s) in the polling sequence.
 */
- (void)tagReaderSession:(NFCTagReaderSession *)session didDetectTags:(NSArray<__kindof id<NFCTag>> *)tags API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(watchos, macos, tvos) {
    _currentTag = [tags firstObject];
    NSData *data ;
    if (self.currentTag.type == NFCTagTypeMiFare) {
        id<NFCMiFareTag> mifareTag = [self.currentTag asNFCMiFareTag];
        data = mifareTag.identifier;
    }else if (self.currentTag.type == NFCTagTypeISO15693){
        id<NFCISO15693Tag> mifareTag = [self.currentTag asNFCISO15693Tag];
        data = mifareTag.identifier;
    }else if (self.currentTag.type == NFCTagTypeISO15693){
        id<NFCISO15693Tag> mifareTag = [self.currentTag asNFCISO15693Tag];
        data = mifareTag.identifier;
    }else{
        NSLog(@"未识别出NFC格式");
    }
        
    NSString *str = [self convertDataBytesToHex:data];
    NSLog(@"tagReaderSession didDetectTags str:%@", str);
    
    //识别成功处理
    [session invalidateSession];
}
     
     
     
- (NSString *)convertDataBytesToHex:(NSData *)dataBytes {
    if (!dataBytes || [dataBytes length] == 0) {
        return @"";
    }
    NSMutableString *hexStr = [[NSMutableString alloc] initWithCapacity:[dataBytes length]];
    [dataBytes enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) {
        unsigned char *dataBytes = (unsigned char *)bytes;
        for (NSInteger i = 0; i < byteRange.length; i ++) {
            NSString *singleHexStr = [NSString stringWithFormat:@"%x", (dataBytes[i]) & 0xff];
            if ([singleHexStr length] == 2) {
                [hexStr appendString:singleHexStr];
            } else {
                [hexStr appendFormat:@"0%@", singleHexStr];
            }
        }
    }];
    return hexStr;
}



@end

至此,NFC标签Tag读取功能代码完成。

三、小结

iOS开发-CoreNFC实现NFC标签Tag读取功能

学习记录,每天不停进步。

相关推荐
CCTV果冻爽16 分钟前
Android 源码集成可卸载 APP
android
秋月霜风1 小时前
mariadb主从配置步骤
android·adb·mariadb
Python私教2 小时前
Python ORM 框架 SQLModel 快速入门教程
android·java·python
编程乐学3 小时前
基于Android Studio 蜜雪冰城(奶茶饮品点餐)—原创
android·gitee·android studio·大作业·安卓课设·奶茶点餐
problc4 小时前
Android中的引用类型:Weak Reference, Soft Reference, Phantom Reference 和 WeakHashMap
android
IH_LZH4 小时前
Broadcast:Android中实现组件及进程间通信
android·java·android studio·broadcast
去看全世界的云4 小时前
【Android】Handler用法及原理解析
android·java
机器之心5 小时前
o1 带火的 CoT 到底行不行?新论文引发了论战
android·人工智能
机器之心5 小时前
从架构、工艺到能效表现,全面了解 LLM 硬件加速,这篇综述就够了
android·人工智能