61
57

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

iOS11 Core NFCを使ってみた

Last updated at Posted at 2017-12-16

iOS11になって、Core NFCというフレームワークが追加されました。
これはNFC(近距離無線通信)を利用したタグとの通信が出来るフレームワークです。

現状では読み取り専用で、しかも専用のアプリを起動しなければいけないそうです。
Androidアプリでは「NFCタグを端末に近づけるとアプリを起動する」といったことができますが、iPhoneではまだそのようなバックグラウンドからNFCの検知イベントでアプリを立ち上げるなどはできません。

ですが、長年さまざまな人が待望した機能ではあります。
実験する価値はあると思っています。

今回はCore NFCを使ったサンプルのアプリの紹介です。
コード量はすくないですが、ハマリポイントもあったので皆さんのお役に立てればと思います。

動作環境

  • Xcode9.2
  • iPhoneX iOS 11.1.2

NFCタグをゲットする

Core NFCを利用したいなら兎にも角にも最初はNFCタグをどこからか入手しなければ行けません。
幸いAmazonで10枚入りのモノが売っていたのでそちらを購入します。

サンワサプライ NFCタグ(10枚入り) 白 MM-NFCT

2017/12/17現在、870円ととても安くなっています。

AndroidでNFCタグにデータを書き込む

残念なことに、現在Core NFCはNFCタグのデータを読み込むことはできても書き込むことはできません。
「サンワサプライ NFCタグ」はデータがない状態で販売されているので何かしらの方法でデータを書き込むことが必要です。

一番簡単なのがAndroidのアプリを使うことです。
私はNFC Toolsというアプリを使って書き込みをしてみました。
image.png

Writeタブの「Add a record」から書き込むデータを指定して「Write / 30 Bytes」セルをタップ、書き込みたいNFCタグを近づけるとデータを書き込めます。

image.png

iOS側の実装

NFCタグを使うには次の段階を踏む必要があります。

  • Info.plistにNFCReaderUsageDescriptionキーを追加
  • ケイパビリティをONにする
  • NFC読み取りの実装をする

Info.plistにNFCReaderUsageDescriptionキーを追加

NFCの利用は位置情報やカメラの利用と同じようにユーザーに許可を求める必要があります。
Info.plistに次のKeyと説明文言を追加します。

<key>NFCReaderUsageDescription</key>
<string>[ユーザーへアプリがNFCを利用する説明を記述]</string>

Xcodeのプロパティリスト表示ではPrivacy - NFC Scan Usage Descriptionというキーを追加すればOKです。

スクリーンショット 2017-12-16 23.33.54.jpg

ケイパビリティをONにする

続いてケイパビリティNear Field Communication Tag ReadingをONにします。

スクリーンショット 2017-12-16 23.36.00.jpg

エンタイトルメントファイルが追加されます。

これで認証系の事前準備は終了です。
次からコードを書いていきます。

NFC読み取りの実装をする

いよいよ実装していきます。
ViewControllerに実装していきたいと思います。

CoreNFCフレームワークをインポートして、NFCNDEFReaderSessionDelegateプロトコルを適応させます。

import UIKit
import CoreNFC

class ViewController: UIViewController, NFCNDEFReaderSessionDelegate {
    var session: NFCNDEFReaderSession?

読み取り開始

    //読み取りボタンを押した
    @IBAction func readNFC(_ sender: UIButton) {
        if NFCNDEFReaderSession.readingAvailable {
            session = NFCNDEFReaderSession(delegate: self, queue: nil, invalidateAfterFirstRead: false)
            session?.alertMessage = "NFCタグをiPhoneに近づけてください"
            session?.begin()
        } else {
            print("NFCが使えません")
        }
    }

NFCが使える端末かどうかはNFCNDEFReaderSession.readingAvailableで判定ができます。trueなら利用できfalseなら利用できません。
現在iPhone7/7Plus、iPhone8/8Plus、iPhoneXで利用ができます。

NFCNDEFReaderSessionのイニシャライズでNFC読み取りのセッションを作成します。
第三引数のinvalidateAfterFirstReadは連続でNFCタグを読み取るかどうかのフラグです。trueなら最初に読み取った時点でセッションを終了します。falseならタイムアウトするまで連続で読み取ります。

session?.alertMessageでシステムが表示した読み取りUIの説明文言を指定できます。

session?.begin()で読み取り開始です。

システムが用意する読み取りUIが表示されます。

IMG_0079.jpg

赤く丸をつけたところがsession?.alertMessageで指定した文字列です。

デリゲートを受け取る

NFCNDEFReaderSessionDelegateは2つのメソッドを実装しなければいけません

readerSession(_:didInvalidateWithError:)readerSession(_:didDetectNDEFs:)です。

readerSession(_:didInvalidateWithError:)はエラーが発生した場合に呼ばれます。
ユーザーがシステムの読み取りUIの「キャンセル」を押すか読み取りがタイムアウト(現状60秒)しても呼ばれます。

    /// 読み取りエラーが起こった時呼ばれる。ユーザーがキャンセルボタンを押すか、タイムアウトしたときに呼ばれる。
    func readerSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) {
        print("error:\(error.localizedDescription)")
    }

NFCが無事に読み取れるとreaderSession(_:didDetectNDEFs:)が呼ばれます。

/// 読み取りに成功したら呼ばれる。
func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) {

    for message in messages {
        for record in message.records {
            print(String(data: record.payload, encoding: .utf8)!)
        }
    }
}

NFCの情報はmessage引数からNFCNDEFMessageの配列として受け取れます。通常は1つのタグにメッセージは1つだそうです。

NFCNDEFMessageインスタンスはvar records:[NFCNDEFPayload]を持っています。
NFCタグには1つまたは複数のレコードを含みます。

このrecodepayloadプロパティ値を読み取ればOKです。

#実際にやってみた。

Androidアプリ「NFC Tools」から自分のブログのURLであるblog.personal-factory.comのデータを書き込みます。

iOSでアプリをビルドしてタグを近づけるとUIがチェックマークに変わり、タグのデータが出力されました

IMG_841EAA24B1EA-1.jpeg

出力文字列

blog.personal-factory.com

成功ですね。

ハマったこと

物品管理として使おうかと思ったので、社内のテスト端末であるiPhone5cにNFCタグを貼り付けたのです。
紹介したNFCタグはシールとなっていて、どこでも貼り付けられるようになっています。
ところが、一行に認識せず、タイムアウトエラーが出てしまっていました。

1時間悩んで、他のタグでやると今度は認識しました。
どうやら金属に貼り付けると認識できないことがあるようです。
試しにどこにも貼り付けないで近づけると認識しました。

このNFCタグの特徴なのか、iPhoneXの精度の問題なのかはまだ確認していないです。

ビジネスとして物品管理などを行う場合は、他のメーカーのNFCタグも試して、精度を確認した方がいいかと思いました。

61
57
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
61
57

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?