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设置为NOif (@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读取功能
学习记录,每天不停进步。