OC-NFC

作者: ChaosHeart | 来源:发表于2021-01-09 08:31 被阅读0次

    一:工程配置

    (1)点击Capablity,选择Near Field Communication Tag Reading


    截屏2020-12-29 10.34.47.png

    (2)在info.plist中配置权限(Privacy - NFC Scan Usage Description)


    截屏2020-12-29 10.36.30.png
    (3)激活App ID的相关功能
    aHR0cHM6Ly91cGxvYWQtaW1hZ2VzLmppYW5zaHUuaW8vdXBsb2FkX2ltYWdlcy85NjY5MjMtYTFlMjIzMjNlMzIzMjg1My5wbmc.png

    二代码:

    //
    //  NFCManager.h
    //  Runner
    //
    //  Created by macmini on 2020/12/29.
    //
    
    #import <Foundation/Foundation.h>
    #import <CoreNFC/CoreNFC.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    typedef 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;//多标签识别
    
    ///单例
    + (instancetype)shareInstance;
    
    ///扫描
    - (void)scanTagWithSuccessBlock:(NFCScanSuccessBlock)scanSuccessBlock andErrorBlock:(NFCScanErrorBlock)scanErrorBlock;
    
    ///获取扫描后的解析的结果
    - (NSMutableArray *)getdataStr:(NFCNDEFMessage *)message;
    
    ///写入
    - (void)writeMessage:(NFCNDEFMessage *)message ToTagWithSuccessBlock:(NFCWriteSuccessBlock)writeSuccessBlock andErrorBlock:(NFCWritErrorBlock)writErrorBlock;
    
    ///判断是否支持读功能
    + (NFCSupportsStatus)isSupportsNFCReading;
    
    ///判断是否支持写功能
    + (NFCSupportsStatus)isSupportsNFCWrite;
    
    ///获取类型名数组
    + (NSArray*)getNameFormatArray;
    
    ///获取类型名字
    + (NSString*)getNameFormat:(NFCTypeNameFormat)typeName;
    
    ///获取类型结构体
    + (NFCTypeNameFormat)getNFCTypeNameFormat:(NSString*)typeName;
    
    @end
    
    NS_ASSUME_NONNULL_END
    
    
    //
    //  NFCManager.m
    //  Runner
    //
    //  Created by macmini on 2020/12/29.
    //
    
    #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 - 单例
    ///强指针,应用结束才会死
    static id _instance;
    
    ///外调单例方法
    + (instancetype)shareInstance
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _instance = [[self alloc] init];
        });
        return _instance;
    }
    
    ///根本上只建立一个对象,只开辟一个内存
    + (instancetype)allocWithZone:(struct _NSZone *)zone {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _instance = [super allocWithZone:zone];
        });
        return _instance;
    }
    
    ///防止copy时,新建立一个对象,保证只开辟一个内存
    -  (id)copyWithZone:(nullable NSZone *)zone
    {
        return _instance;
    }
    
    
    
    #pragma mark - NFC
    
    
    ///扫描
    - (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;
        }
    }
    
    ///开始NFC
    - (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;
    }
    
    ///createAMessage
    - (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 - NFC代理
    ///读取失败回调-读取成功后还是会回调这个方法
    - (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){
        
    }
    
    ///获取扫描后的解析的结果
    - (NSMutableArray *)getdataStr:(NFCNDEFMessage *)message
    {
        NSMutableArray *mArr = [@[] mutableCopy];
        for (NFCNDEFPayload *record in message.records) {
            NSString *dataStr = [[NSString alloc] initWithData:record.payload encoding:NSUTF8StringEncoding];
            NSLog(@"扫描结果 :%@", dataStr);
            [mArr addObject:dataStr];
        }
        return mArr;
    }
    
    @end
    
    

    参考:

    https://blog.csdn.net/songkuipeng/article/details/103768616

    相关文章

      网友评论

          本文标题:OC-NFC

          本文链接:https://www.haomeiwen.com/subject/hlrfoktx.html