Swift CoreNFC as quick as possible
NFC stands for “Near Field Communication”. Two electronic devices can transmit data through NFC when they are distanced fewer than 4 cm apart. NFC can be used for electronic payment. It was invented many years ago but it has just been introduced by Apple to iPhone series since the launch of iPhone7 in 2016. To test an app with NFC feature, a real device must be used instead of an iOS simulator.
Tosetup a NFC project, the “NFC Tag Reading” must be enabled in the “App Services” session during registering an App ID in the Apple Developer Console.
A screenshot of the App Services session during registering an App ID in Apple Developer Console
Secondly, the “Near Field Communication Tag Reading” has to be enabled at the “Capabilities” tab of the app target session.
“Near Field Communication Tag Reading” in the “Capabilities” tab
Thirdly, “Privacy — NFC Scan Usage Description” must be added to the Info.plist. Otherwise, app is terminated by
libsystem_kernel.dylib __pthread_kill with no error message at Xcode console.
IfNFC in your app is an optional feature and you probably wants those device without NFC chip to run your app, the CoreNFC.framework MUST be set to “Optional” in iOS 12.
Else, app will be crash at start with the following message showing “CoreNFC.framework” cannot be loaded.
dyld: Library not loaded: /System/Library/Frameworks/CoreNFC.framework/CoreNFC
Referenced from: /var/containers/Bundle/Application/DF6D870C-4928-40F6-A242-BAB9C07B3737/BaseProject.app/BaseProject
Reason: image not found
Let’s start coding now!
How to interpret the NFC information from [NFCNDEFMessage] Object?
The NFC information is stored inside the
record within the
NFCNDEFMessage object contains a list of “record” and each record contains:
1. “payload” in form of NSData and contains tag message
- NFC tag original message: “abc”
- Original message in ASCII code:
— 0: 97 [a]
— 1 : 98 [b]
— 2 : 99 [c]
— 0 : 2 [START OF TEXT] in ASCII table.
— 1 : 101 [e]
— 2 : 110 [n]
— 3 : 97 [a]
— 4 : 98 [b]
— 5 : 99 [c]
Why there is “en” in front of the original message “abc”?
“All language codes MUST be done according to RFC 3066 [RFC3066]. The language code MAY NOT be omitted. The language code length is encoded in the six least significant bits of the status byte. Thus it is easy to find by masking the status byte with the value 0x3F.”
— NFC Data Exchange Format (NDEF) Technical Specification, NFC Forum
Thus, the payload of record has to be advanced by 3 before converting to a String for displaying!
Handling result at the didDetectNDEFs
Case 1 (init with parameter —
If NFC reader session is initialised with
invalidateAfterFirstRead equals true, NFC tag reading dialog will be automatically dismissed after tag is successfully detected and the blue-tick animation is completed (last for around 3 seconds).
Due to this 3-second time gap, UIAlertController is presented but covered by the NFC tag reading dialog completely, and user cannot interact with any
UIAlertAction. This results in a bad user experience. See below gif:
Case 2 (init with parameter —
NFC reading tag dialog can be dismissed manually if NFCNDEFReaderSession is initialised with
invalidateAfterFirstRead equals false.
However, the NFC session can actually be dismissed after the blue-tick animation is completed. Thus, calling
nfcSession.invalidate() right before showing UIAlertController does not guarantee the NFC tag reading dialog is actually dismissed. There is an around 0.5 second time gap for this. Thus, the UIAlertController is still shown behind the NFC tag reading dialog for a noticeable short period of time. User experience is not perfect.
Case 3 (init with parameter —
invalidateAfterFirstRead: false + 1s delay):
Finally, the solution to provide the best user experience is to give an around 1 second delay to the DispatchQueue to ensure that the NFC tag reading dialog is completely dismissed before showing an UIAlertController.
- The NFCNDEFReaderSession has a default 60 seconds time out for reading NFC tag. Below is the error message for time out.
Session is invalidated due to maximum session timeout
2. Alert message in the NFC tag reading dialog is optimised for 3 lines of wordings. The 4th line is truncated at the end.
3. Titles of NFC tag reading dialog and cancel button are not customisable and the locale is fixed to the device locale.
- Ensure “NFC Tag Reading” is enabled for your app at the Apple Developer Console.
- “Near Field Communication Tag Reading” has to be checked in app capabilities list.
- Make sure your real device has NFC chip or setting CoreNFC.framework to be an optional framework.
- “Privacy — NFC Scan Usage Description” must be filled in to request the permission of using user’s NFC chip.
- Create the NFCNDEFReaderSession with
invalidateAfterFirstRead: false, and give one second delay to show any UIAlertController or navigate to any page.
didDetectNDEFscallback is run in background thread and never update UI directly.
Have a nice day and enjoy programming ^_^ !