iOS11のCoreNFCを使う


WWDC2017で発表のあったCoreNFCを使ってみました。テストした範囲ではNDEF(NFC Data Exchange Format)が読み込めるようです。FelicaID読み取りはできないようです。

![IMG_1362.PNG](https://qiita-image-store.s3.amazonaws.com/0/14768/e7528de4-a7c4-f15c-b2e3-4b7266961f38.png "IMG_1362.PNG") ![IMG_0121.PNG](https://qiita-image-store.s3.amazonaws.com/0/14768/65e2403c-46e8-2b10-f193-6935b5196c0f.png "IMG_0121.PNG")


+ CoreNFC

https://developer.apple.com/documentation/corenfc

## 動作環境

+ XCode Version 9.0 beta (9M136h)
+ iOS11(Build 15A5278f)

# サンプルコード

作りかけですが動作しているサンプルコードを以下に置いておきます。
https://github.com/bellx2/ios11NFCTest/

※provisioningファイルの設定が必要です。

# 設定方法

CoreNFCを利用するためには、以下のような設定が必要です。正式版になれば他の機能拡張と同じくXCodeのCapabilitiesで設定するだけ1.2は不要になるはずです。

1.ADCサイトでProvisioningファイルのNFC Readingを有効にします。

![スクリーンショット 2017-06-06 23.44.53.png](https://qiita-image-store.s3.amazonaws.com/0/14768/971b1701-27b9-8fcf-7103-16536f383a13.png "スクリーンショット 2017-06-06 23.44.53.png")

このprovsioningファイルを利用します。

2.entitlementsファイルにNFCの設定を入れます

![スクリーンショット 2017-06-07 00.00.38.png](https://qiita-image-store.s3.amazonaws.com/0/14768/aa7fbd19-df06-da69-ee1e-8300c66aa368.png "スクリーンショット 2017-06-07 00.00.38.png")


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

entitlementsファイルが生成されていない場合にはCapabiritiesから「Siri」などを選ぶと生成されます。

3.Info.plistに「NFCReaderUsageDescription」を追加します（ダイアログに表示されます）

![スクリーンショット 2017-06-07 00.01.50.png](https://qiita-image-store.s3.amazonaws.com/0/14768/2dcf5a1f-5aff-de17-746c-0ec20516806e.png "スクリーンショット 2017-06-07 00.01.50.png")

```
<key>NFCReaderUsageDescription</key>
    <string>NFCのカードをかざしてください</string>
```
4.プロジェクトにCoreNFCを追加します

![スクリーンショット 2017-06-06 19.31.23.png](https://qiita-image-store.s3.amazonaws.com/0/14768/cdf1e33d-c190-3687-0070-b2728221da0b.png "スクリーンショット 2017-06-06 19.31.23.png")



# プログラム解説

NFCNDEFReaderSessionDelegateを設定します。

```
class ViewController: UIViewController, NFCNDEFReaderSessionDelegate{
	....
}
```

NFCNDEFReaderSessionを生成します。invalidateAfterFirstReadをfalseにするとNFCを複数回読みます。trueの場合は１回スキャンすると終了します。

```
let session:NFCNDEFReaderSession = NFCNDEFReaderSession(delegate: self, queue: nil, invalidateAfterFirstRead: true)
session.begin()
```

begin()するとダイアログが出てきて読み出しモードとなります。


値が取得できるとreaderSession(_ ,didDetectNDEFs)にてデータが返ります。

```
func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) {
        for message in messages{
            for payload in message.records {
                print ("Payload Data: \(payload.payload)")
            }
        }
}
```

エラーもしくは終了の場合はreaderSession(_ , didInvalidateWithError)が呼ばれます。

```
func readerSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) {
        print("Error: \(error.localizedDescription)")
    }
}
```

# 注意点

+ 実機もしくはGenericDeviceを選択しないと「No Such module 'CoreNFC'」と出てコンパイルできません。オートコンプリートなども効きません。

![スクリーンショット 2017-06-06 23.47.53.png](https://qiita-image-store.s3.amazonaws.com/0/14768/f70f43bd-a715-189f-c53c-c59f2279e055.png "スクリーンショット 2017-06-06 23.47.53.png")

+ provisioningに設定がされていない場合は以下のようなエラーがでます。

![スクリーンショット 2017-06-07 00.05.00.png](https://qiita-image-store.s3.amazonaws.com/0/14768/c23df439-b1dd-f502-b08a-c3dce3efffca.png "スクリーンショット 2017-06-07 00.05.00.png")


+ entitlementsファイルが設定がされていない場合は202エラー、Info.plistにNFCReaderUsageDescriptionエントリーが無い場合はサクッと落ちます...。

# その他参考

+ StackOverflow
https://stackoverflow.com/questions/44380305/ios-11-core-nfc-any-sample-code

+ NDEF
http://nfcpy.readthedocs.io/en/latest/topics/ndef.html