본문 바로가기
프로그래밍/Swift

iOS CoreNFC.framework, NFC Tag Reader 개발(Objective-C)

by Mr-후 2017. 12. 28.
반응형


iOS CoreNFC.framework, NFC Tag Reader 개발(Objective-C)


오늘은 회사에서 추진하는 사업 일환으로 NFC 관련해서 iOS Objective-c 기반의 CoreNFC 기술에 대해 개발 절차를 정리해서 올려 두고자 합니다. 

아이폰은 애플페이 외엔 NFC리딩이 안되던 상황에서 이번에 iOS11버전이 나오면서 iPhone7이상의 단말에서 CoreNFC를 사용할 수 있도록 프레임워크가 추가 되었습니다. 

이미 관련 앱들이 쏟아져 나오기도 했고 여러 말들이 많았는데요... 생각보다 단말의 사양이 높게 책정이 되어 아이폰6, 6S, 6+사용자들까지 흡수하지 못한 부분이 아쉽기는 합니다. 

iPhoneSE까지 범위를 넓혀 좀더 많은 단말에서 CoreNFC를 사용할 수 있도록 했다면 좋았을 것 같네요. 

또한 iOS의 CoreNFC는  호스트 카드 에뮬레이션 [Host Card Emulation] 지원이 되지 않아, 안드로이드에서 지원되는  NFC의 기능을 모두 수용할 수는 없습니다. 

또, 단말 OS단에서 바로 태깅을 할 수는 없고, 특정 앱에 종속되어 스캔을 하고 결과를 받아야 하는 다른 점이 있습니다. 

아이폰의 상단부분에 스캔 영역이 있는 것 같고 실제 구현은 생각보다 간단하고 쉽습니다. 

다음 절차대로 진행하시면 됩니다. 

1. 개발 하는 앱 정보(애플 개발자 사이트) 앱ID 설정에서 아래 표시된 NFC Tag reading 옵션을 Enabled한다.

2. 물론, 프로비져닝을 해서 모바일프로비저닝을 다운로드 하신 후 앱 프로젝트 설정에서 다음 두 가지를 설정해주시면 됩니다. 

1. 프로젝트에 CoreNFC.framework를 추가한다. 

2. 프로젝트 Capabillities 탭의 Near Field Communication Tag Reading을 ON으로 변경한다. 


3. 프로젝트 Info탭에서  Privacy - NFC Scan Usage Description 키를 추가하고 Read NFC Tags.라고 입력한다. 


3. 실제 코드 구현을 하면 됩니다. 

1. 실제 구현 파일에서 NFCNDEFReaderSessionDelegate를 따른다고 선언하고 Delegate Method를 구현하시면 됩니다. 

@interface CoreNFCViewController ()<NFCNDEFReaderSessionDelegate>

@property (nonatomic, strong)   NFCNDEFReaderSession *session NS_AVAILABLE_IOS(11.0);

@end

2. 스캔 세션의 시작은 아래 함수와 같은 방식으로 하면 됩니다. 

- (void)beginSession

{

    if (@available(iOS 11.0, *)) {

        _session = [[NFCNDEFReaderSession alloc] initWithDelegate:self queue:dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT) invalidateAfterFirstRead:NO];

        [_session beginSession];

    }

}

3. Delegate Method가 호출 되는 부분인데, 실제 스캔을 해서 완료가 되면 호출이 되고 세션이 종료되면 호출이 되고 합니다. 간단하기 때문에 금방 이해가 될 것이라고 판단이 됩니다. 

#pragma mark - NFCNDEFReaderSessionDelegate

- (void)readerSession:(nonnull NFCNDEFReaderSession *)session didInvalidateWithError:(nonnull NSError *)error NS_AVAILABLE_IOS(11.0) {

    NSLog(@"Error: %@", [error debugDescription]);

    

    if (error.code == NFCReaderSessionInvalidationErrorUserCanceled) {

        // User cancellation.

        return;

    }

    

    dispatch_async(dispatch_get_main_queue(), ^{

        _logView.text = [NSString stringWithFormat:@"[%@] Error: %@ (%ld)\n%@",

                         [NSDate date],

                         [error localizedDescription],

                         (long)error.code,

                         _logView.text];

    });

}


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

    for (NFCNDEFMessage *message in messages) {

        for (NFCNDEFPayload *payload in message.records) {

            NSLog(@"Payload: %@", payload);

            const NSDate *date = [NSDate date];

            dispatch_async(dispatch_get_main_queue(), ^{

                _logView.text = [NSString stringWithFormat:

                                 @"[%@] Identifier: %@ (%@)\n"

                                 @"[%@] Type: %@ (%@)\n"

                                 @"[%@] Format: %d\n"

                                 @"[%@] Payload: %@ (%@)\n%@",

                                 date,

                                 payload.identifier,

                                 [[NSString alloc] initWithData:payload.identifier

                                                       encoding:NSASCIIStringEncoding],

                                 date,

                                 payload.type,

                                 [[NSString alloc] initWithData:payload.type

                                                       encoding:NSASCIIStringEncoding],

                                 date,

                                 payload.typeNameFormat,

                                 date,

                                 payload.payload,

                                 [[NSString alloc] initWithData:payload.payload

                                                       encoding:NSASCIIStringEncoding],

                                 _logView.text];

                NSLog(@"Payload = %@", [[NSString alloc] initWithData:payload.payload

                                                             encoding:NSASCIIStringEncoding]);

            });

        }

    }

    [_session invalidateSession];

}




실제 구현된 모습의 스크린샷입니다. 참고하세요 


스캔이 준비된 상태, NFC 태깅을 위해 카드나 NFC를 앱 상단에 가져다 대면 Reader하게 되고 

그 결과 내용은 아래 처럼 확인을 하면 됩니다. 

간단하죠? 




반응형