Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save treastrain/f73334e4c7ef7591226277abe95ec071 to your computer and use it in GitHub Desktop.
Save treastrain/f73334e4c7ef7591226277abe95ec071 to your computer and use it in GitHub Desktop.
iOS 14 での Core NFC による交通系ICカードの残高読み取りサンプル(集まれSwift好き!Swift愛好会スピンオフ WWDC20セッション要約会 @ Online July 9, 2020)
// Created by treastrain on 2020/07/08.
// Copyright © 2020 treastrain / Tanaka Ryoga. All rights reserved.
//
/// 1. プロジェクトの TARGET から開発している iOS Application を選び、Signing & Capabilities で Near Field Communication Tag Reading を有効にする(Near Field Communication Tag Reader Session Formats が entitlements ファイルに含まれている必要がある)。
/// 2. Near Field Communication Tag Reader Session Formats の中に "NFC tag-specific data protocol (TAG)" が含まれていることを確認する。
/// 3. 開発している iOS Application の Info.plist に "Privacy - NFC Scan Usage Description (NFCReaderUsageDescription)" を追加する。
/// 4. 開発している iOS Application の Info.plist に "ISO18092 system codes for NFC Tag Reader Session (com.apple.developer.nfc.readersession.felica.systemcodes)" を追加し、読み取る際に使用する FeliCa システムコード `0003` を記述する。
import UIKit
import CoreNFC
class ViewController: UIViewController, NFCTagReaderSessionDelegate {
var session: NFCTagReaderSession?
override func viewDidLoad() {
super.viewDidLoad()
guard NFCTagReaderSession.readingAvailable else {
// ...
return
}
self.session = NFCTagReaderSession(pollingOption: .iso18092, delegate: self)
self.session?.alertMessage = "カードを平らな面に置き、カードの下半分を隠すように iPhone をその上に置きます。"
self.session?.begin()
}
func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) {
guard let tag = tags.first, tags.count == 1 else {
session.invalidate(errorMessage: "タグが見つからなかったか、複数のタグが同時に検出されました。")
return
}
session.connect(to: tag) { (error) in
if let error = error {
session.invalidate(errorMessage: error.localizedDescription)
return
}
guard case .feliCa(let feliCaTag) = tag else {
session.invalidate(errorMessage: "FeliCa タグではないものが検出されました。")
return
}
/*
// iOS 13 まで
feliCaTag.readWithoutEncryption(serviceCodeList: CJRC.Balance.serviceCodeList, blockList: CJRC.Balance.blockList) { (statusFlag1, statusFlag2, blockData, error) in
if let error = error {
session.invalidate(errorMessage: error.localizedDescription)
}
guard statusFlag1 == 0x00, statusFlag2 == 0x00 else {
session.invalidate(errorMessage: "ステータスフラグがエラーを示しています。\(statusFlag1), \(statusFlag2)")
return
}
let data = blockData.first!
let balance = Int(data[11]) + Int(data[12]) << 8
session.alertMessage = "残高: ¥\(balance)"
session.invalidate()
}
*/
// iOS 14 から
feliCaTag.readWithoutEncryption(serviceCodeList: CJRC.Balance.serviceCodeList, blockList: CJRC.Balance.blockList) { (response) in
switch response {
case .success((let statusFlag, let blockData)):
guard statusFlag.statusFlag1 == 0x00, statusFlag.statusFlag2 == 0x00 else {
session.invalidate(errorMessage: "ステータスフラグがエラーを示しています。\(statusFlag)")
return
}
let data = blockData.first!
let balance = Int(data[11]) + Int(data[12]) << 8
session.alertMessage = "残高: ¥\(balance)"
session.invalidate()
case .failure(let error):
session.invalidate(errorMessage: error.localizedDescription)
}
}
}
}
func tagReaderSession(_ session: NFCTagReaderSession, didInvalidateWithError error: Error) {
print("Invalidate error:", error.localizedDescription)
}
func tagReaderSessionDidBecomeActive(_ session: NFCTagReaderSession) {
// ...
}
}
struct CJRC {
struct Balance {
static let serviceCodeList = [Data([0x8B, 0x00])]
static let blockList = [Data([0x80, 0x00])]
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment