#一.说明
1-苹果手机从iPhone6开始装有NFC硬件,但并未对第三方应用开放。因此iPhone6及iPhone6s不能识别NFC标签,但是可以使用系统NFC功能如:刷地铁。
2-苹果从iOS11系统开始开放NFC读取功能,同时要求iPhone7及以上机型。不满足要求则无法读取NFC标签
3-苹果在iOS13系统开放了标签写入功能,想要向标签内写入数据,需要升级系统到iOS13,同样只能写入DNEF格式数据
4-另外苹果只开放DNEF数据格式的NFC标签读取,如果数据格式不满足则无法读取。身份证、地铁卡、银行卡、大部分的工卡都不是DNEF格式,因此无法读取。(空标签只能在iOS13系统下才可以读取到)(NFC标签可以去淘宝购买,价格很便宜 9.9六个还包邮)
5-身份证、地铁卡虽然无法读取到数据,但是可以用苹果官方APP“快捷指令”进行标记,来实现一些新颖玩法(需要iPhoneXS以上机型)
6-关于后台读取,iPhoneXS以上机型支持,屏幕点亮状态下(无需解锁),手机可以读取一些特定数据格式的NFC标签。识别到标签后,可以实现拨打电话,发送邮件等功能(需解锁)
#二.项目推荐
我自己写的一个关于NFC读写的APP,可以直接用来调试NFC标签
https://itunes.apple.com/cn/app/id1492298987
#三.工程配置
1.需要配置Capabilitles。使用NFC需要配置Capabilitles,这会自动为你生成entitlements文件中的必要配置。

2.打开隐私相关设置。向info.plist中添加Privacy - NFC Scan Usage Description。

3.激活App ID的相关功能。如下图所示(自动签名项目系统会自动配置)

#四.代码
1.NFCManager.h

#import <Foundation/Foundation.h>
#import <CoreNFC/CoreNFC.h>NS_ASSUME_NONNULL_BEGINtypedef NS_ENUM(NSInteger, NFCSupportsStatus) {NFCSupportStatusYes,//支持NFCSupportStatusDeviceNo,//硬件不支持NFCSupportStatusnSystemNo,//系统不支持
};API_AVAILABLE(ios(11.0))
typedef void(^NFCScanSuccessBlock)(NFCNDEFMessage *message);
typedef void(^NFCScanErrorBlock)(NSError *error);
typedef void(^NFCWriteSuccessBlock)(void);
typedef void(^NFCWritErrorBlock)(NSError *error);API_AVAILABLE(ios(11.0))
@interface NFCManager : NSObject
@property(nonatomic,copy)NFCScanSuccessBlock scanSuccessBlock;
@property(nonatomic,copy)NFCScanErrorBlock scanErrorBlock;
@property(nonatomic,copy)NFCWriteSuccessBlock writeSuccessBlock;
@property(nonatomic,copy)NFCWritErrorBlock writErrorBlock;
@property(nonatomic,assign) BOOL moreTag;//多标签识别+(NFCManager *)sharedInstance;
-(void)scanTagWithSuccessBlock:(NFCScanSuccessBlock)scanSuccessBlock andErrorBlock:(NFCScanErrorBlock)scanErrorBlock;
-(void)writeMessage:(NFCNDEFMessage *)message ToTagWithSuccessBlock:(NFCWriteSuccessBlock)writeSuccessBlock andErrorBlock:(NFCWritErrorBlock)writErrorBlock;
//判断是否支持读写功能
+(NFCSupportsStatus)isSupportsNFCReading;
+(NFCSupportsStatus)isSupportsNFCWrite;
//获取类型名数组
+(NSArray*)getNameFormatArray;
//获取类型名字
+(NSString*)getNameFormat:(NFCTypeNameFormat)typeName;
//获取类型结构体
+(NFCTypeNameFormat)getNFCTypeNameFormat:(NSString*)typeName;
@endNS_ASSUME_NONNULL_END

1.NFCManager.m

#import "NFCManager.h"API_AVAILABLE(ios(11.0))
@interface NFCManager ()<NFCNDEFReaderSessionDelegate>{BOOL isReading;
}
@property (strong, nonatomic) NFCNDEFReaderSession *session;
@property (strong, nonatomic) NFCNDEFMessage *message;
@end@implementation NFCManager#pragma mark - 单例方法
+(NFCManager *)sharedInstance{static dispatch_once_t onceToken;static NFCManager * sSharedInstance;dispatch_once(&onceToken, ^{sSharedInstance = [[NFCManager alloc] init];});return sSharedInstance;
}
-(void)scanTagWithSuccessBlock:(NFCScanSuccessBlock)scanSuccessBlock andErrorBlock:(NFCScanErrorBlock)scanErrorBlock{self.scanSuccessBlock=scanSuccessBlock;self.scanErrorBlock=scanErrorBlock;isReading=YES;[self beginScan];
}
-(void)writeMessage:(NFCNDEFMessage *)message ToTagWithSuccessBlock:(NFCWriteSuccessBlock)writeSuccessBlock andErrorBlock:(NFCWritErrorBlock)writErrorBlock{self.message=message;self.writeSuccessBlock=writeSuccessBlock;self.writErrorBlock=writErrorBlock;isReading=NO;[self beginScan];
}
+(NFCSupportsStatus)isSupportsNFCReading{if (@available(iOS 11.0,*)) {if (NFCNDEFReaderSession.readingAvailable == YES) {return NFCSupportStatusYes;}else{NSLog(@"%@",@"该机型不支持NFC功能!");return NFCSupportStatusDeviceNo;}}else {NSLog(@"%@",@"当前系统不支持NFC功能!");return NFCSupportStatusnSystemNo;}
}
+(NFCSupportsStatus)isSupportsNFCWrite{if (@available(iOS 13.0,*)) {if (NFCNDEFReaderSession.readingAvailable == YES) {return NFCSupportStatusYes;}else{NSLog(@"%@",@"该机型不支持NFC功能!");return NFCSupportStatusDeviceNo;}}else {NSLog(@"%@",@"当前系统不支持NFC功能!");return NFCSupportStatusnSystemNo;}
}
-(void)beginScan{if (@available(iOS 11.0, *)) {self.session = [[NFCNDEFReaderSession alloc]initWithDelegate:self queue:nil invalidateAfterFirstRead:NO];self.session.alertMessage = @"准备扫描,请将卡片贴近手机";[self.session beginSession];}
}
//获取类型名数组
+(NSArray*)getNameFormatArray{return @[@"Empty",@"NFCWellKnown",@"Media",@"AbsoluteURI",@"NFCExternal",@"Unknown",@"Unchanged"];
}
//获取类型名字
+(NSString*)getNameFormat:(NFCTypeNameFormat)typeName{if (typeName==NFCTypeNameFormatEmpty) {return @"Empty";}else if (typeName==NFCTypeNameFormatNFCWellKnown){return @"NFCWellKnown";}else if (typeName==NFCTypeNameFormatMedia){return @"Media";}else if (typeName==NFCTypeNameFormatAbsoluteURI){return @"AbsoluteURI";}else if (typeName==NFCTypeNameFormatNFCExternal){return @"NFCExternal";}else if (typeName==NFCTypeNameFormatUnknown){return @"Unknown";}else if (typeName==NFCTypeNameFormatUnchanged){return @"Unchanged";}return @"";
}
//获取类型结构体
+(NFCTypeNameFormat)getNFCTypeNameFormat:(NSString*)typeName{if ([typeName isEqualToString:@"Empty"]) {return NFCTypeNameFormatEmpty;}else if ([typeName isEqualToString:@"NFCWellKnown"]){return NFCTypeNameFormatNFCWellKnown;}else if ([typeName isEqualToString:@"Media"]){return NFCTypeNameFormatMedia;}else if ([typeName isEqualToString:@"AbsoluteURI"]){return NFCTypeNameFormatAbsoluteURI;}else if ([typeName isEqualToString:@"NFCExternal"]){return NFCTypeNameFormatNFCExternal;}else if ([typeName isEqualToString:@"Unknown"]){return NFCTypeNameFormatUnknown;}else if ([typeName isEqualToString:@"Unchanged"]){return NFCTypeNameFormatUnchanged;}return NFCTypeNameFormatEmpty;
}
-(NFCNDEFMessage*)createAMessage{NSString* type = @"U";NSData* typeData = [type dataUsingEncoding:NSUTF8StringEncoding];NSString* identifier = @"12345678";NSData* identifierData = [identifier dataUsingEncoding:NSUTF8StringEncoding];NSString* payload1 = @"ahttps://www.baidu.com";NSData* payloadData1 = [payload1 dataUsingEncoding:NSUTF8StringEncoding];if (@available(iOS 13.0, *)) {NFCNDEFPayload *NDEFPayload1=[[NFCNDEFPayload alloc]initWithFormat:NFCTypeNameFormatNFCWellKnown type:typeData identifier:identifierData payload:payloadData1];NFCNDEFMessage* message = [[NFCNDEFMessage alloc]initWithNDEFRecords:@[NDEFPayload1]];return message;} else {return nil;}
}
//停止扫描
-(void)invalidateSession{if (!self.moreTag) {[self.session invalidateSession];}
}
#pragma mark - NFCNDEFReaderSessionDelegate
//读取失败回调-读取成功后还是会回调这个方法
- (void)readerSession:(NFCNDEFReaderSession *)session didInvalidateWithError:(NSError *)error API_AVAILABLE(ios(11.0)){NSLog(@"%@",error);if (error.code == 201) {NSLog(@"扫描超时");}if (error.code == 200) {NSLog(@"取消扫描");}
}
//读取成功回调iOS11-iOS12
- (void)readerSession:(NFCNDEFReaderSession *)session didDetectNDEFs:(NSArray*)messages
API_AVAILABLE(ios(11.0)){dispatch_async(dispatch_get_main_queue(), ^{if (self->isReading) {if (@available(iOS 11.0, *)) {for (NFCNDEFMessage *message in messages) {session.alertMessage = @"读取成功";[self invalidateSession];if (self.scanSuccessBlock) {self.scanSuccessBlock(message);}}}}else{//ios11-ios12下没有写入功能返回失败session.alertMessage = @"写入失败";[self invalidateSession];}});
}
//读取成功回调iOS13
- (void)readerSession:(NFCNDEFReaderSession *)session didDetectTags:(NSArray<__kindof id<NFCNDEFTag>> *)tags API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(watchos, macos, tvos){dispatch_async(dispatch_get_main_queue(), ^{if (tags.count>1) {session.alertMessage=@"存在多个标签";[session restartPolling];return;}id  tag=tags.firstObject;[session connectToTag:tag completionHandler:^(NSError * _Nullable error) {if (error) {session.alertMessage = @"连接NFC标签失败";[self invalidateSession];return;}[tag queryNDEFStatusWithCompletionHandler:^(NFCNDEFStatus status, NSUInteger capacity, NSError * _Nullable error) {if (error) {session.alertMessage = @"查询NFC标签状态失败";[self invalidateSession];return;}if (status == NFCNDEFStatusNotSupported) {session.alertMessage = @"标签不是NDEF格式";[self invalidateSession];return;}if (self->isReading) {//读[tag readNDEFWithCompletionHandler:^(NFCNDEFMessage * _Nullable message, NSError * _Nullable error) {if (error) {session.alertMessage = @"读取NFC标签失败";[self invalidateSession];}else if (message==nil) {session.alertMessage = @"NFC标签为空";[self invalidateSession];return;}else {session.alertMessage = @"读取成功";[self invalidateSession];if (self.scanSuccessBlock) {self.scanSuccessBlock(message);}}}];}else{//写数据[tag writeNDEF:self.message completionHandler:^(NSError * _Nullable error) {if (error) {session.alertMessage = @"写入失败";if (self.writErrorBlock) {self.writErrorBlock(error);}}else {session.alertMessage = @"写入成功";if (self.writeSuccessBlock) {self.writeSuccessBlock();}}[self invalidateSession];}];}}];}];});
}
//
- (void)readerSessionDidBecomeActive:(NFCNDEFReaderSession *)session API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(watchos, macos, tvos){}
@end

iOS NFC开发(读标签与写标签)相关推荐

  1. iOS开发 - ANPs推送通知 标签: 推送通知ANPs远程推送、本地推送

    iOS开发 - ANPs推送通知 标签: 推送通知ANPs远程推送本地推送 2015-05-03 14:12 3510人阅读 评论(0) 收藏 举报 本文章已收录于:  iOS知识库  分类: [IO ...

  2. Android NFC开发详解 总结和NFC读卡实例解析

    文章目录 前言 一.什么是NFC? 二.基础知识 1.什么是NDEF? 2.NFC技术的操作模式 3.标签的技术类型 4.实现方式的分类 5.流程 三.获取标签内容 1.检查环境 2.获取NFC标签 ...

  3. 一文读懂基于PN532和S50的NFC开发

    基于PN532和S50的NFC开发 1. NFC概述 NFC(Near Field Communication)近场通信,这个技术由非接触式射频识别(RFID)演变而来,由飞利浦半导体(现恩智浦半导体 ...

  4. python 全栈开发,Day45(html介绍和head标签,body标签中相关标签)

    python 全栈开发,Day45(html介绍和head标签,body标签中相关标签) 一.html介绍 1.web标准 web准备介绍: w3c:万维网联盟组织,用来制定web标准的机构(组织) ...

  5. HTML前端开发入门之表单标签/labei标签/datalist标签

    ##表单标签 <!DOCTYPE html> <html lang="en"> <head>     <meta charset=&quo ...

  6. HTML5前端开发入门之H系列标签,P标签和Hr标签

    ##H系列标签(Header1~Header2) -作用:用于给文本添加标题语义 -格式: -<h1>xxxxxx</h2> -注意点: -H标签是用来给文本添加标题语义的,而 ...

  7. J2EE平台WEB组件开发中如何使用定制标签

    J2EE平台WEB组件开发中如何使用定制标签       J2EE PLATFORM WEB组件开发涉及SERVLET 和JSP技术,SERVLET和JSP各有其优缺点.JVAVABEAN和定制标签对 ...

  8. 前端开发 html第二课 自结束标签 注释 标签中的属性 文档声明 进制 字符编码 文档使用 VScode 实体 meta标签 语义化标签 块元素和行内元素 布局标签

    1 自结束标签 标签一般成对出现,但是也存在一些自结束标签 如: 多"/"和没有"/"区别不大 2 注释 注释的作用: 注释中的内容会被浏览器忽略,不会在网页中 ...

  9. python 全栈开发,Day46(列表标签,表格标签,表单标签,css的引入方式,css选择器)

    一.列表标签 列表标签分为三种. 1.无序列表<ul>,无序列表中的每一项是<li> 英文单词解释如下: ul:unordered list,"无序列表"的 ...

最新文章

  1. Atom介绍和安装步骤
  2. 30分钟git命令入门到放弃
  3. [转]互联网产品经理必上的九个资讯+分析类网站
  4. 怎样用Java自制优秀的图片验证码?这样!
  5. tourist取模模板
  6. 【IDEA】推荐一些好用的IDEA插件
  7. iOS开发 蓝牙技术4.0详解
  8. 合并分ER图产生的冲突
  9. (转)mysql 无法设置外键的原因总结
  10. 简单的Oracle触发器使用
  11. 开发者需要了解的nodejs中require的机制
  12. java中的配置文件
  13. Unity 事件番外篇:UnityEvent
  14. k8s集群ip地址变更后设置
  15. 针对手机连WIFI微信公众号等图片加载缓慢问题——解决方案
  16. 云计算在教育方面的应用
  17. mysql启动不了的原因_mysql启动不了是什么原因
  18. 深入剖析斐波拉契数列
  19. 将json数据格式转化成excel插件JsonExportExcel.js的使用demo
  20. MySQL创建用户添加权限

热门文章

  1. UTF-8 and Unicode FAQ for Unix/Linu
  2. 前端规范css篇——样式重置,字体颜色,行间距
  3. 计算机小组作业心得体会,小组活动工作反思
  4. 【校招VIP】线上实习 推推 书籍详情模块 前端开发文档周最佳
  5. 20210122 matlab波特图从rad/s 改为HZ
  6. Skeleton-Based Action Recognition with Spatial Reasoning and Temporal Stack Learning 论文赏析
  7. 分享:为什么说精细化管理才是餐饮软件的关键?
  8. 修复被破坏了的linux文件系统分区表
  9. Fabric 账本数据块结构解析(一):如何解析账本中的智能合约交易数据
  10. Java集合总结Map篇