ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Building an NFC Tag-Reader App
    iOS Swift/애플 문서 한글화 2023. 6. 6. 15:56

    Sample Code 

    이 문서는 https://developer.apple.com/documentation/corenfc/building_an_nfc_tag-reader_app 를 한글화한 문서입니다.

    NFC 태그 리더 앱 만들기

    NDEF 메시지가 포함된 NFC 태그를 읽습니

    Overview

    이 프로젝트의 샘플 코드는 앱에서 Core NFC를 사용하여 NDEF(NFC 데이터 교환 형식) 데이터가 포함된 타입 1~ 5의 근거리 무선 통신(NFC) 태그를 읽는 방법을 보여줍니다. 이 샘플을 사용하려면 프로젝트를 다운로드하고 Xcode를 사용하여 빌드합니다. 빌드 후 iPhone에서 샘플 앱을 실행시킵니다. NFC와 통신을 하려면 스캔 버튼을 탭하여 태그 스캔을 시작한 다음 휴대폰을 NFC 태그 근처에 가져다 댑니다.  태그를 읽기 위해 샘플 앱은 NFC NDEF 리더 세션을 생성하고 delegate 를 제공합니다. 실행 중인 리더 세션은 NFC 태그에 폴링하고 NDEF 메시지가 포함된 태그를 찾으면  delegate를 호출해 메시지를 전달합니다. delegate는 사용자가 나중에 메시지를 볼 수 있도록 해당 메시지를 저장합니다. 

    NFC 태그를 감지하기위한 앱 설정 

    NFC 리더 앱을 만들기 위해서 첫번째로 할 일은 Target에 Signing & Capabilities 탭에서 Near Field Communication Tag Reading을 추가합니다. 다음으로 타겟에 대한 entitlement 파일에 Near Field Communication Tag Reader Session Formats 카를 추가합니다.

     

    다음으로 해당 앱이 NFC를 사용하고 있음을 알리기 위해 info.plist 파일에 NFCReaderUsageDescription 키에 문자열을 추가합니다. 값에는 앱이 기기의 NFC 리더에 엑세스해야 하는 이유를 설멍하는 문자열을 입력합니다. 앱이 이 키와 문자열을 제공하지 않으면 태그를 읽으려 할 때 앱이 종료됩니다. 

     

    리더 세션의 시작 

    init(delegate:queue:invalidateAfterFirstRead:) 초기화 메서드를 호출하고 다음을 전달하여 NFCNDEFReaderSession 개체를 만듭니다.

    • 리더 세션에 대한 delegate 
    • delegate의 함수가 호출 될 때 사용할 디스패치 큐
    • 리더 세션이 단일 태그만 읽을지 아니면 여러 태그를 읽을 지 여부를 결정하기 위한  invalidAfterFirstRead 플래그

    리더 세션을 생성한 후 alertMessage 프로퍼티를 설정하여 사용자에게  지침을 제공합니다. 예를 들어 사용자에게 ‘아이템에 대해 자세히 알아보려면 아이템 근처에 iPhone을 대십시오’라고 말할 수 있습니다. 폰이 NFC 태그를 스캔하는 동안 시스템은 이 메시지를 사용자에게 표시합니다. 마지막으로 begin()을 호출하여 리더 세션을 시작합니다. 이렇게 하면 폰에. 무선 주파수 폴링이 활성화되고 폰이 태그 검색을 시작합니다. 샘플 앱은 사용자가 스캔 버튼을 탭할 때 리더 세션을 시작합니다. 앱은 첫번째 태그를 읽은 후 세션을 무효화 하도록 리더 세션을 구성합니다. 추가 태그를 읽으려면 사용자가 스캔 버튼을 다시 눌러야 합니다.

    @IBAction func beginScanning(_ sender: Any) {
        guard NFCNDEFReaderSession.readingAvailable else {
            let alertController = UIAlertController(
                title: "Scanning Not Supported",
                message: "This device doesn't support tag scanning.",
                preferredStyle: .alert
            )
            alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
            self.present(alertController, animated: true, completion: nil)
            return
        }
    
        session = NFCNDEFReaderSession(delegate: self, queue: nil, invalidateAfterFirstRead: false)
        session?.alertMessage = "Hold your iPhone near the item to learn more about it."
        session?.begin()
    }

    주) 해당 코드는 스캔 버튼을 탭할 때 호출되는 코드로 NFCReraderSession.readingAvailable 을 통해 사용가능 여부를 확인하고 NFCNDEFReaderSession을 생성합니다. delegate는 현재 클래스인 self로 설정하고 있는데 이는 delegate의 구현을 해당 클래스에서 수행하기 때문입니다. 해당 코드에는 invalidateAfterFirstRead 값이 false로 되어 있는데 해당 문서의 내용 상 true가 맞습니다.

     

    리더 세션  딜리케이트 프로토콜 구현 

    리더 세션에는 NFCNDEFReaderSessionDelegate 프로토콜을 준수하는 위임 개체를 구현해  ReaderSession이 다음과 같은 경우에 이벤트를 전달하면 이를 처리할 수 있습니다.

    • NDEF 메시지를 수신할 때 
    • 세션 종료 또는 오류 발생으로 세션이 무효화 될 때
    class MessagesTableViewController: UITableViewController, NFCNDEFReaderSessionDelegate {

    NDEF 메시지 읽기

    리더 세션이 새 NDEF 메시지를 수신할 때 마다 세션은 readerSession(_:didDetectedNDEFs:) 메서드를 호출하여 딜리게이트에 메시지를 전송합니다. 이것은 수신된 데이터로 유용한 작업을 수행할 수 있는 기회로,  샘플 앱에서는 사용자가 나중에 볼 수 있도록 메시지를 저장합니다.

    func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) {
        DispatchQueue.main.async {
            // Process detected NFCNDEFMessage objects.
            self.detectedMessages.append(contentsOf: messages)
            self.tableView.reloadData()
        }
    }

    주) 해당 앱은 수신된 데이터를 detectedMessages 배열에 추가하고 테이블 뷰를 리로드해 화면에 데이터를 보여줍니다. 

     

    무효화된 리더 세션 처리

    리더 세션이 끝나면 위임 메서드 readerSession(_:didInvalidateWithError:)를 호출하고 세션 종료 이유를 제공하는 오류 개체를 전달합니다. 가능한 이유는 다음과 같습니다.

    •  리더 세션이 첫 번째 태그를 읽은 후 세션을 무효화하도록 구성되었고 폰이 NFC 태그를 성공적으로 읽었을 때 입니다. 오류 코드는 NFCReaderError.Code.readerSessionInvalidationErrorFirstNDEFTagRead입니다.
    • 사용자가 세션을 취소했거나 앱에서 invalidate()를 호출하여 세션이 종료된 경우 입니다. 오류 코드는 NFCReaderError.Code.readerSessionInvalidationErrorUserCanceled입니다.
    • 리더 세션 유지 중 에 오류가 발생한 경우 입니다. 전체 오류 코드 목록은 NFCReaderError.Code  를 참조하세요.

    샘플 앱에서 딜리게이터는 단일 태그 리더 세션이 유지 되는 중 첫 번째 태그를 읽거나 사용자가 세션을 취소하는 것 이외의 이유로 리더 세션이 종료될 때 경고를 표시합니다. 또한 무효화된 리더 세션은 재사용할 수 없으므로 샘플 앱은 self.session을 nil로 설정합니다.

    func readerSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) {
        // Check the invalidation reason from the returned error.
        if let readerError = error as? NFCReaderError {
            // Show an alert when the invalidation reason is not because of a
            // successful read during a single-tag read session, or because the
            // user canceled a multiple-tag read session from the UI or
            // programmatically using the invalidate method call.
            if (readerError.code != .readerSessionInvalidationErrorFirstNDEFTagRead)
                && (readerError.code != .readerSessionInvalidationErrorUserCanceled) {
                let alertController = UIAlertController(
                    title: "Session Invalidated",
                    message: error.localizedDescription,
                    preferredStyle: .alert
                )
                alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
                DispatchQueue.main.async {
                    self.present(alertController, animated: true, completion: nil)
                }
            }
        }
    
    
        // To read new tags, a new session instance is required.
        self.session = nil
    }

     

    NDEF 메시지 쓰기 

    태그에 쓰기 위해 샘플 앱은 새 리더 세션을 시작합니다. 태그에 NDEF 메시지를 쓰려면 이 세션이 활성 상태여야 하므로 태그로 부터 첫 번째 메시지를 수신한 이후에 세션이 무효화되지 않게 하기 위해 invalidateAfterFirstRead를 false로 설정합니다.

    @IBAction func beginWrite(_ sender: Any) {
        session = NFCNDEFReaderSession(delegate: self, queue: nil, invalidateAfterFirstRead: false)
        session?.alertMessage = "Hold your iPhone near an NDEF tag to write the message."
        session?.begin()
    }

    리더 세션이 태그를 감지하면 readerSession(_:didDetectNDEFs:). 딜리게이트 메서드가 호출됩니다. 첫 번째 태그를 읽은 후 세션이 무효화되지 않기 때문에 세션이 하나 이상의 태그를 감지할 수 도 있습니다. 이 경우 샘플 앱은 하나의 태그에만 쓰기를 수행하기 때문에세션이 하나의 태그만 감지했는지 확인합니다. 세션이 둘 이상을 감지한 경우 앱은 사용자에게 태그를 제거하도록 요청한 다음 폴링을 다시 시작하여 태그를 다시 검색합니다. 앱이 태그가 하나만 있음을 확인한 후 태그에 연결하고 쓰기 가능한지 확인합니다. 그런 다음 앱은 이전에 읽은 NDEF 메시지를 태그에 씁니다.

    func readerSession(_ session: NFCNDEFReaderSession, didDetect tags: [NFCNDEFTag]) {
        if tags.count > 1 {
            // Restart polling in 500 milliseconds.
            let retryInterval = DispatchTimeInterval.milliseconds(500)
            session.alertMessage = "More than 1 tag is detected. Please remove all tags and try again."
            DispatchQueue.global().asyncAfter(deadline: .now() + retryInterval, execute: {
                session.restartPolling()
            })
            return
        }
        
        // Connect to the found tag and write an NDEF message to it.
        let tag = tags.first!
        session.connect(to: tag, completionHandler: { (error: Error?) in
            if nil != error {
                session.alertMessage = "Unable to connect to tag."
                session.invalidate()
                return
            }
            
            tag.queryNDEFStatus(completionHandler: { (ndefStatus: NFCNDEFStatus, capacity: Int, error: Error?) in
                guard error == nil else {
                    session.alertMessage = "Unable to query the NDEF status of tag."
                    session.invalidate()
                    return
                }
    
    
                switch ndefStatus {
                case .notSupported:
                    session.alertMessage = "Tag is not NDEF compliant."
                    session.invalidate()
                case .readOnly:
                    session.alertMessage = "Tag is read only."
                    session.invalidate()
                case .readWrite:
                    tag.writeNDEF(self.message, completionHandler: { (error: Error?) in
                        if nil != error {
                            session.alertMessage = "Write NDEF message fail: \(error!)"
                        } else {
                            session.alertMessage = "Write NDEF message successful."
                        }
                        session.invalidate()
                    })
                @unknown default:
                    session.alertMessage = "Unknown NDEF tag status."
                    session.invalidate()
                }
            })
        })
    }

    백그라운드 에서 태그 읽기의 지원 

    iOS가 백그라운드에서 태그를 읽을 수 있도록 앱을 설정하는 방법을 알아보려면 “Adding Supported for Background Tag Reading"을 참고하세요.

     

     

     

    'iOS Swift > 애플 문서 한글화' 카테고리의 다른 글

    Recording movies in alternative formats  (0) 2023.06.07
    Exporting video to alternative formats  (0) 2023.06.07
    Loading media data asynchronously  (0) 2023.06.07
    NFCNDEFReaderSession  (0) 2023.06.06
    Core NFC  (0) 2023.06.06

    댓글

Designed by Tistory.