{"id":13995702,"url":"https://github.com/hansemannn/iOS-NFC-Example","last_synced_at":"2025-07-22T22:32:00.926Z","repository":{"id":142791143,"uuid":"93724665","full_name":"hansemannn/iOS-NFC-Example","owner":"hansemannn","description":"📱 Use the Core NFC API in Swift/iOS","archived":false,"fork":false,"pushed_at":"2024-06-09T18:33:22.000Z","size":60,"stargazers_count":523,"open_issues_count":5,"forks_count":70,"subscribers_count":49,"default_branch":"master","last_synced_at":"2024-11-28T15:38:02.894Z","etag":null,"topics":["example","ios","nfc","swift"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hansemannn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-06-08T08:20:09.000Z","updated_at":"2024-11-23T08:35:25.000Z","dependencies_parsed_at":"2024-11-28T15:32:41.532Z","dependency_job_id":"3457428f-b422-442f-a2c7-b0e73b4e3253","html_url":"https://github.com/hansemannn/iOS-NFC-Example","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hansemannn%2FiOS-NFC-Example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hansemannn%2FiOS-NFC-Example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hansemannn%2FiOS-NFC-Example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hansemannn%2FiOS-NFC-Example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hansemannn","download_url":"https://codeload.github.com/hansemannn/iOS-NFC-Example/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":227190301,"owners_count":17745243,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["example","ios","nfc","swift"],"created_at":"2024-08-09T14:03:33.463Z","updated_at":"2024-11-29T18:30:51.020Z","avatar_url":"https://github.com/hansemannn.png","language":"Swift","readme":"# 📱 iOS NFC-Example\n\nA quick example showing how to use the Core NFC API in iOS and Swift.\n\n## Prerequisites\n* NFC-permissions added to your Info.plist:\n```xml\n\u003ckey\u003eNFCReaderUsageDescription\u003c/key\u003e\n\u003cstring\u003eYOUR_PRIVACY_DESCRIPTION\u003c/string\u003e\n ```\n* Xcode capability \"`Near Field Communication Tag Reading`\" enabled **OR**\n* NFC capability-key added to your project's `.entitlements` file:\n```xml\n\u003ckey\u003ecom.apple.developer.nfc.readersession.formats\u003c/key\u003e\n\u003carray\u003e\n  \u003cstring\u003eNDEF\u003c/string\u003e\n\u003c/array\u003e\n```\n* Provisioning Profile entitled with the `NFC Tag Reading` capability:\n\u003cimg src=\"https://abload.de/img/68747470733a2f2f6162606s1g.png\" width=\"500\" alt=\"iOS Developer Center: NFC Capability\" /\u003e\n\n## Understanding NDEF-Records\n\nIn order to work with NFC-tags, it is fundamental to understand the NDEF (NFC Data Exchange Format) specification.\nWhenever `CoreNFC` discovers a new tag, the `didDetectNDEFs` delegate method will provide an array of NDEF messages\n(`[NFCNDEFMessage]`). Usually, there is only one NDEF message included, but the specification keeps it flexible to provide\nmultiple messages at the same time. \n\nEvery `NFCNDEFMessage` includes an array of payload-records (`[NFCNDEFPayload]`) that hold the actual information\nthe developer is interested in. There are currently four (undocumented) properties in the `CoreNFC` framework to access those:\n\n1. `typeNameFormat`: The type name format (TNF) describes the data-structure of the related record. There are seven types that can be used via the enumeration `NFCTypeNameFormat`:\n    1. `.empty`: There record is empty and does not contain any information\n    2. `.nfcWellKnown`: The payload is known and defined by the Record Type Definition (RTD), for example RTD Text / URI.\n    3. `.media`: The payload includes a final / intermediate chunk of data defined by the mime-type ([RFC2046](http://www.faqs.org/rfcs/rfc2046.html))\n    4. `.absoluteURI`: The record contains an absolute URI resource ([RFC3986](http://www.faqs.org/rfcs/rfc3986.html))\n    5. `.nfcExternal`: The record contains a value that uses an external RTD name specifiction\n    6. `.unknown`: The record type is unknown, the type length has to be set to `0`.\n    7. `.unchanged`: The record payload is the intermediate or even final chunk of data. This can be used when there is a large number of data that is splitted into multiple chunks of data.\n2. `type`: The Record Type Definition (RTD) of the record. iOS describes it as a `Data` type, Android has constants (like [`RTD_TEXT`](https://developer.android.com/reference/android/nfc/NdefRecord.html#RTD_TEXT))\n3. `identifier`: A unique identifier of the record.\n4. `payload`: The actual payload of the record. Accessing it depends on the specified `typeNameFormat` as described above.\n\n## Getting Started\nFirst, import the `CoreNFC` framework. \n```swift\nimport CoreNFC\n```\nNext, create 2 properties: Your session and an array of discovered tag-messages:\n```swift\n// Reference the NFC session\nprivate var nfcSession: NFCNDEFReaderSession!\n    \n// Reference the found NFC messages\nprivate var nfcMessages: [[NFCNDEFMessage]] = []\n```\nAfter that, assign and start your `nfcSession`:\n```swift\n// Create the NFC Reader Session when the app starts\nself.nfcSession = NFCNDEFReaderSession(delegate: self, queue: nil, invalidateAfterFirstRead: false)\n\n// A custom description that helps users understand how they can use NFC reader mode in your app.\nself.nfcSession.alertMessage = \"You can hold you NFC-tag to the back-top of your iPhone\"\n\n// Begin scanning\nself.nfcSession.begin()\n```\nFinally, listen for NFC-related events by writing an extension that implements the `NFCNDEFReaderSessionDelegate`:\n```swift\nextension NFCTableViewController : NFCNDEFReaderSessionDelegate {\n    \n    // Called when the reader-session expired, you invalidated the dialog or accessed an invalidated session\n    func readerSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) {\n        print(\"Error reading NFC: \\(error.localizedDescription)\")\n    }\n    \n    // Called when a new set of NDEF messages is found\n    func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) {\n        print(\"New NFC Tag detected:\")\n        \n        for message in messages {\n            for record in message.records {\n                print(\"Type name format: \\(record.typeNameFormat)\")\n                print(\"Payload: \\(record.payload)\")\n                print(\"Type: \\(record.type)\")\n                print(\"Identifier: \\(record.identifier)\")\n            }\n        }\n        \n        // Add the new messages to our found messages\n        self.nfcMessages.append(messages)\n        \n        // Reload our table-view on the main-thread to display the new data-set\n        DispatchQueue.main.async {\n            self.tableView.reloadData()\n        }\n    }\n}\n```\nOptionally, since we use a `UITableView` to display the discovered messages, prepare your table-view delegates:\n```swift\nextension NFCTableViewController {\n    \n    override func numberOfSections(in tableView: UITableView) -\u003e Int {\n        return self.nfcMessages.count\n    }\n    \n    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -\u003e Int {\n        return self.nfcMessages[section].count\n    }\n    \n    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -\u003e String? {\n        let numberOfMessages = self.nfcMessages[section].count\n        let headerTitle = numberOfMessages == 1 ? \"One Message\" : \"\\(numberOfMessages) Messages\"\n        \n        return headerTitle\n    }\n    \n    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -\u003e UITableViewCell {\n        let cell = tableView.dequeueReusableCell(withIdentifier: \"NFCTableCell\", for: indexPath) as! NFCTableViewCell\n        let nfcTag = self.nfcMessages[indexPath.section][indexPath.row]\n        \n        cell.textLabel?.text = \"\\(nfcTag.records.count) Records\"\n        \n        return cell\n    }\n}\n```\nThat's it! Run the app on your device and scan your NFC NDEF-Tag.\n\n### Example Output\n```\nNew NFC Messages (1) detected:\n - 2 Records:\n   - TNF (TypeNameFormat): NFC Well Known\n   - Payload: google.com\n   - Type: 1 bytes\n   - Identifier: 0 bytes\n\n   - TNF (TypeNameFormat): NFC Well Known\n   - Payload: enTest\n   - Type: 1 bytes\n   - Identifier: 0 bytes\n```\n\n## User Experiences\nInitial tests of another user (thanks [@tinue](https://github.com/tinue)) shown these following results:\n1. Scanning an NDEF-tag usually works once directly after rebooting the iPhone. From then on, it may or may not work, usually it doesn't work and another reboot is required.\n2. If the RFID-tag is fresh (empty), or does not contain an NDEF-tag (e.g. a credit-card), the reader times out (error 201).\n3. If the RFID-tag contains encrypted sectors, the reader throws error 200 (`readerSessionInvalidationErrorUserCanceled`).\n\n## RFID Functionality\nIn this example, we used the `NFCNDEFReaderSession` to handle NDEF NFC-chips. There actually is another class inside\n`CoreNFC`, called `NFCISO15693ReaderSession`. [ISO15693](https://de.wikipedia.org/wiki/ISO_15693) is the specification\nfor RFID-tags, and it comes along with own delegates and a class describing an RFID-tag (`NFCISO15693Tag`).\n\nI have played around with that API as well and added the `RFID` button to the current implementation, so you can switch\nbetween NFC- and RFID-detection. You can even send custom commands to the RFID-chip as demonstrated in the\n`readerSession:didDetectTags:` delegate and the `NFCISO15693CustomCommandConfiguration` class.\n\n## References\nI used the following resources to get started with NDEF NFC-tags:\n- [x] [https://flomio.com/2012/05/ndef-basics/](https://flomio.com/2012/05/ndef-basics/)\n- [x] [https://learn.adafruit.com/adafruit-pn532-rfid-nfc/ndef](https://learn.adafruit.com/adafruit-pn532-rfid-nfc/ndef)\n- [x] [https://developer.android.com/reference/android/nfc/NdefRecord.html](https://developer.android.com/reference/android/nfc/NdefRecord.html)\n- [x] [https://gototags.com/nfc/ndef/](https://gototags.com/nfc/ndef/)\n\n## Cross-Platform Usage\nIf you are using a cross-platform solution for your application, [Appcelerator Titanium](http://www.appcelerator.com/mobile-app-development-products/) has an open source [NFC module](https://github.com/appcelerator-modules/ti.nfc) for both Android and iOS.\n\n## Author\nHans Knöchel ([@hansemannnn](https://twitter.com/hansemannnn))\n","funding_links":[],"categories":["Swift"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhansemannn%2FiOS-NFC-Example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhansemannn%2FiOS-NFC-Example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhansemannn%2FiOS-NFC-Example/lists"}