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

    一:工程配置 (1)点击Capablity,选择Near Field Communication Tag Read...

网友评论

      本文标题:OC-NFC

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