Search code examples
iosnfcbetacore-nfc

iOS 11 Core NFC - any sample code?


I just installed the first iOS 11 beta to an iPhone 7 and am interested in trying the NFC. There's nothing about it in settings. I am wondering if there's any sample code out there showing how to read a tag. Can anyone show how to use the Core NFC SDK, in a code snippet?


Solution

  • In the Apple Developer site, create a new App ID and make sure that NFC Tag Reading is enabled.

    Dev portal capabilities

    Add the following lines to your .plist file:

    <key>NFCReaderUsageDescription</key>
    <string>NFC Tag!</string>
    

    and these to the entitlements file:

    <key>com.apple.developer.nfc.readersession.formats</key>
        <array>
            <string>NDEF</string>
        </array>
    

    It should look something like this in the corresponding files:

    enter image description here

    Also Core NFC can be enabled via the Capabilities tab in Xcode.

    enter image description here

    Objective-c

    Import CoreNFC

    #import <CoreNFC/CoreNFC.h>
    

    and set the delegate:

    @interface YourViewController : UIViewController <NFCNDEFReaderSessionDelegate>
    

    In viewDidLoad:

    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        NFCNDEFReaderSession *session = [[NFCNDEFReaderSession alloc] initWithDelegate:self queue:dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT) invalidateAfterFirstRead:NO];
        [session beginSession];
    }
    

    In the delegate callback:

    - (void) readerSession:(nonnull NFCNDEFReaderSession *)session didDetectNDEFs:(nonnull NSArray<NFCNDEFMessage *> *)messages {
    
        for (NFCNDEFMessage *message in messages) {
            for (NFCNDEFPayload *payload in message.records) {
                NSLog(@"Payload data:%@",payload.payload);
            }
        }        
    }
    

    You must also add the didInvalidateWithError delegate callback or you'll not conform with protocol:

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

    You can stop the reader with:

    [session invalidateSession];
    

    Swift 3/4

    Import CoreNFC

    import CoreNFC
    

    and set the delegate:

    class YourViewController: UIViewController, NFCNDEFReaderSessionDelegate
    

    In viewDidLoad:

    override func viewDidLoad() {
            super.viewDidLoad()
    
            let session = NFCNDEFReaderSession(delegate: self,
                          queue: DispatchQueue(label: "queueName", attributes: .concurrent), invalidateAfterFirstRead: false)  
            session?.begin()
        }
    

    In the delegate callback:

    func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) {
      for message in messages {
        for record in message.records {
          print(record.payload)
        }
      }
    }
    

    You can stop the reader with:

    session.invalidateSession
    

    Usage

    After launching the view you should immediately see the iOS NFC reader dialog like so:

    iOS NFC reader dialog

    Once this dialog appears you have about a second to place the iPhone near the NFC tag you want to read. Otherwise, the field is deactivated (this seems to be a bug on Apple's end). I often needed to cancel and retry to get consistent readings. More details here.