iOSアプリ開発でSQLiteを使う FMDB

iOSアプリ開発でSQLiteを使う FMDB はじめに iOSアプリ開発で、SQLiteを使ってデータ管理する方法を調べてみました。SQLiteをそのまま使うよりは、SQLiteをラッパーしたFMDBライブラリを使うとより便利です。そちらもご紹介いたします。 iOSアプリ開発ではじめてSQLiteを使う libsqlite3.tbdをプロジェクトに追加 libsqlite3.tbdをプロジェクトに追加します。 Xcodeのプロジェクトナビゲータでプロジェクト名を選択し、「Build Phases」タブに移動します。「Link Binary With Libraries」セクションで、+ボタンを押して、libsqlite3.tbdを追加します。 ソースコード // // ViewController.swift // SampleSqlite // // Created by Toshihiko Arai on 2024/10/11. // import UIKit import SQLite3 // 日本語文字を登録するために必要な定数 let SQLITE_TRANSIENT = unsafeBitCast(-1, to: sqlite3_destructor_type.self) class ViewController: UIViewController { var db: OpaquePointer? override func viewDidLoad() { super.viewDidLoad() // データベースの準備 if let databasePath = createDatabase() { openDatabase(path: databasePath) createTable() insertData(name: "空条承太郎", age: 40) insertData(name: "空条徐倫", age: 17) fetchData() } } // データベースのパスを取得して作成 func createDatabase() -> String? { let fileURL = try? FileManager.default .url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) .appendingPathComponent("sample.sqlite") return fileURL?.path } // データベースのオープン func openDatabase(path: String) { if sqlite3_open(path, &db) != SQLITE_OK { print("データベースを開くことができません") } } // テーブルの作成 func createTable() { let createTableString = """ CREATE TABLE IF NOT EXISTS Person( Id INTEGER PRIMARY KEY AUTOINCREMENT, Name CHAR(255), Age INTEGER); """ var createTableStatement: OpaquePointer? if sqlite3_prepare_v2(db, createTableString, -1, &createTableStatement, nil) == SQLITE_OK { if sqlite3_step(createTableStatement) == SQLITE_DONE { print("テーブルの作成に成功しました") } else { print("テーブルの作成に失敗しました") } } else { print("テーブル作成の準備に失敗しました") } sqlite3_finalize(createTableStatement) } // データの挿入 func insertData(name: String, age: Int32) { let insertStatementString = "INSERT INTO Person (Name, Age) VALUES (?, ?);" var insertStatement: OpaquePointer? if sqlite3_prepare_v2(db, insertStatementString, -1, &insertStatement, nil) == SQLITE_OK { sqlite3_bind_text(insertStatement, 1, name, -1, SQLITE_TRANSIENT) sqlite3_bind_int(insertStatement, 2, age) if sqlite3_step(insertStatement) == SQLITE_DONE { print("データの挿入に成功しました") } else { print("データの挿入に失敗しました") } } else { print("挿入ステートメントの準備に失敗しました") } sqlite3_finalize(insertStatement) } // データの取得 func fetchData() { let queryStatementString = "SELECT * FROM Person;" var queryStatement: OpaquePointer? if sqlite3_prepare_v2(db, queryStatementString, -1, &queryStatement, nil) == SQLITE_OK { while sqlite3_step(queryStatement) == SQLITE_ROW { let id = sqlite3_column_int(queryStatement, 0) let name = String(cString: sqlite3_column_text(queryStatement, 1)) let age = sqlite3_column_int(queryStatement, 2) print("Query Result:") print("ID: \(id), Name: \(name), Age: \(age)") } } else { print("クエリの準備に失敗しました") } sqlite3_finalize(queryStatement) } } SQLiteのデータ型 SQLiteには4つの基本的なストレージクラス(データ型)があります。 ...

公開: 2024年10月11日 · 更新: 2026年2月25日 · Toshihiko Arai
Square Terminal APIを使った会計処理

Square Terminal APIを使った会計処理

この記事の範囲と前提 以前、オリジナルの Android アプリから Square Terminal 端末と連携して会計処理をする仕事に携わったときの記録です。公式ドキュメントが分散しており目当ての情報に辿り着くまで苦労したので、プロジェクトの備忘録として大まかな手順をまとめました。 この記事では次のことを扱います。 Square Terminal 端末をアプリ側のカードリーダーとして使う前提 Terminal API でデバイスコードを発行し、端末とペアリングするまで アプリ側からチェックアウト(金額表示)リクエストを送り、状態を確認・キャンセルするまで ACCESS_TOKEN、device_id、idempotency_key といった必須の値の扱い Webhook の利用シーンと最低限の運用注意 前提として次が必要です。 Square Developer アカウントと、そこで作成した Application 一式(ACCESS_TOKEN・location_id 取得用) 本番アカウントでサインインできる Square Terminal 端末 1 台以上 端末を叩く側のアプリケーション(この記事では Android アプリを想定していますが、HTTP が投げられれば言語は問いません) curl または Square API Explorer など、API を叩ける環境 サンプルコードでは Square-Version として 2024-06-04 と 2024-04-17 の両方が出てきます。これは当時実際に動作確認したバージョンで、現行の API バージョンに合わせて読み替えてください。Square API は後方互換を保ったままバージョン番号が定期的に上がっていく仕組みです。 この記事の内容に関する個別の質問にはお答えできません。あくまで「当時こうやって動かしたメモ」として参照してください。 公式ドキュメントとツール 実装中によく参照したものは次の通りです。手元から開きやすいよう、最初にまとめておきます。 Terminal API クイックスタート(公式) Square Terminal の支払いフロー(公式) CreateDeviceCode(API Explorer) 関連する記事 Android アプリ側の作りや、ACCESS_TOKEN を扱う中間サーバーの作り方は別記事にまとめています。Square 連携を組み立てる前後で参考になりそうなものを並べておきます。 ...

公開: 2024年6月19日 · 更新: 2026年5月30日 · Toshihiko Arai

ESP32でBluetooth Classicを使ってAndroidと通信する

この記事では、 ESP32 から Android アプリへ Bluetooth Classic(SPP)で文字列を送信し、Android 側で表示する ところまでを最小構成で作ります。ESP32 側は Arduino IDE の BluetoothSerial、Android 側は Kotlin の BluetoothSocket を使い、UART のシリアル通信と同じ感覚で書ける構成です。 逆方向の BLE で iOS と通信する例や、BLE と Classic の住み分けを先に把握したい場合は、後半の関連記事 も合わせて参考にしてください。 先に要点 ESP32 側は BluetoothSerial で SerialBT.begin("デバイス名") するだけで、SPP のサーバ側が立ち上がります Android からは事前に OS の Bluetooth 設定でペアリングしておき、アプリ側では SPP 標準の UUID 00001101-0000-1000-8000-00805F9B34FB で BluetoothSocket を張ります Android 12 以降は BLUETOOTH_CONNECT のランタイム権限が必要なので、AndroidManifest.xml への記述だけでなくアプリ側でのリクエストも忘れずに行います BLE 通信側で iOS と Lチカしたい場合ははじめてのBLE通信、iOSからESP32のLチカ 、BLE で ESP32 から iOS にデータを送りたい場合はESP32からiOSへBLEでデータを送信する を参照してください ゴール 動画のように、ESP32からBluetooth Classic経由でAndroidアプリへデータを送信し、データを表示するまでをゴールとします。 ...

公開: 2024年1月20日 · 更新: 2026年5月29日 · Toshihiko Arai

はじめてのBLE通信、iOSからESP32のLチカ

はじめに この記事では、 iPhone(iOS)から ESP32 へ BLE 経由で命令を送り、ESP32 につないだ LED を点灯・消灯させる ところまでを作ります。iOS 側は CoreBluetooth、ESP32 側は Arduino IDE で書いた BLE Server の最小構成です。 必要なものは、ESP32 開発ボード(NodeMCU-32S や ESP32-DevKitC など)、LED、1kΩ 程度の抵抗、ブレッドボードと配線材、それに iPhone とビルド用の Mac です。配線は GPIO13 → LED のアノード → LED のカソード → 抵抗 → GND の順でつなぎます。 このあと BLE の用語を一通り整理し、サービス・キャラクタリスティック・UUID といった「相手を見つけて値を渡す」しくみを確認したうえで、ESP32 と iOS のサンプルコードを並べていきます。BLE の概念にすでに馴染みがあれば、Bluetooth Lチカプログラム まで読み飛ばしても構いません。 先に要点 ESP32 をペリフェラル(BLE Server)、iPhone をセントラル(BLE Client)として扱います iPhone のボタンが押されたら "0" または "1" の文字列を BLE Write で送り、ESP32 側で GPIO13 の HIGH/LOW を切り替えます 接続には サービス UUID と キャラクタリスティック UUID の2つが ESP32 側と iOS 側で一致している必要があります ESP32 から iOS へ値を返したい場合(センサ値などの Notify 送信)は、続編の ESP32 から iOS へ BLE でデータを送信する でまとめています Arduino IDE で ESP32 を書き込めるところまで進めていない場合は、先に ESP32 で L チカするまでの設定 を済ませておくと進めやすいです 「Bluetooth」名前の由来 Bluetoothは直訳すると 青い歯 です。その由来は10世紀のデンマークとノルウェーの王様の「Harald Blåtand Gormsen」の名前から来ているそうです。Blåtandを英語に翻訳するとBluetoothなのです。Harald王は北欧を統一した王様で、乱立する無線通信規格も Harald王のようにBluetoothで統一したいという願いが込められてます。 ...

公開: 2021年7月14日 · 更新: 2026年5月28日 · Toshihiko Arai

【ESP32】BLE通信、ESP32からiOSでデータ受信

はじめに 今回は BLE通信を使って、ESP32から送られたデータをiOS端末で受信 します。ESP32をペリフェラル、iOSをセントラルとして扱い、ESP32側で読み取った値を Notify で送る構成です。 この形にしておくと、ESP32につないだセンサの値をiPhoneアプリ側で受け取り、画面に表示できます。Wi-Fiを使わずに近距離で値を渡したいときの入口として、前回のLチカ記事と合わせて読むと流れを追いやすいです。 先に要点 ESP32側は BLE Server としてサービス、キャラクタリスティック、Notify を用意します iOS側は CoreBluetooth で対象サービスをスキャンし、キャラクタリスティックを見つけて通知を登録します 値を受け取る処理は didUpdateValueFor characteristic で行います UUID が一致しないと接続後に値を受け取れないので、ESP32側とiOS側で同じ値を使います 前回のおさらい はじめに前回のおさらいです。BLE通信をはじめるには、 アドバタイジング で目的の サービス を持つ ペリフェラル を見つけ、 キャラクタリスティック を取得する必要がありました。よってペリフェラルの サービスUUIDとキャラクタリスティックUUIDの2つ以上が必要 になります。 前回は、iOSからESP32へデータを送信してLチカを実現させました。よってキャラクタリスティックの属性には Write が必要でした。 今回は、ESP32のデータをiOSで受信したいので Notify属性を使ってデータを受信 します。 ところで、この記事で扱うiOSとESP32は次のような関係になります。混乱しないよう気をつけてください。 iOS ESP32 セントラル ペリフェラル マスタ スレイブ クライアント サーバ ESP32のUUIDをそれぞれ次のように決めました。 項目 値 SERVICE UUID 4fafc201-1fb5-459e-8fcc-c5c9c331914b CHARACTERISTIC UUID beb5483e-36e1-4688-b7f5-ea07361b26a8 これらの値はESP32のサンプルの値を使用してます。必要あればこちらのジェネレータでUUIDを生成して書き換えてください。 https://www.uuidgenerator.net/ BLE通信でESP32のデータをiOSで受信するプログラム 概要 ESP32のGPIO32へ可変抵抗を取り付け、読み取ったアナログ値をiOSでBLE経由で受信する プログラムを作っていきます。 可変抵抗は両側をGNDと3.3Vに接続し、真ん中の端子をGPIOへ繋いでください。BLE通信を開始したらNotify通知を設定し、抵抗値をiOSで受け取りUILabeで表示させます。 ESP32(ペリフェラル) ESP32(ペリフェラル)のArduinoで書いたプログラムです。前回のBluetooth Lチカとそれほど変わりません。ESP32でデータを通知するにはキャラクタリスティックにデータをセットして通知します。 pCharacteristic->setValue(str); pCharacteristic->notify(); なお、ここでは文字列をセットしましたが、int型などもセットできるようです。 ...

公開: 2021年7月14日 · 更新: 2026年4月29日 · Toshihiko Arai

【Swift】リングバッファーのQueueでベンチマークテスト

Q? 突然ですが、プログラミングでQueueを処理するにはどうしますか? SwiftでQueueを作ってみました。次の単純なプログラムでサクッと作れました。 var max:Int! var data:[Any] = [] init(_ max:Int) { self.max = max } func enqueue(_ obj:Any) -> Bool { if data.count > self.max - 1 { return false } data.append(obj) return true } func dequeue() -> Any? { if data.count > 0 { let obj = data[0] data.remove(at: 0) return obj } return nil } しかしこのアルゴリズムは、問題があります。とくにC言語の場合で、致命的な問題になる場合があります。 このプログラムでは配列の先頭を削除してますが、内部では同時に配列全体を前方にシフトする処理を行っているので、配列が大きくなればなるほど速度が遅くなってしまうのです。 リングバッファ 何か良い方法があるのではと思いQueueのプログラムを調べていくと、リングバッファと呼ばれるアルゴリズムが見つかりました。 サイズの決まった配列を作り、輪のように見立てて考えます。0番から順番にデータを入れていきます。一周回ったら、また0番に戻ってデータを入れていきます。こうすることで、配列をシフトする処理の必要が無くなります。カウントの管理はheadとnumの値で管理します。enqueueしたらnumカウントを1プラスするようにし、dequeueしたら、headカウンタを1プラスします。enqueueすべきインデックスはhead+num番となります。dequeueすべきインデックスはhead番となります。 リングバッファーの説明およびプログラミングは、こちらのサイトが大変参考になりました。 http://www.cc.kyoto-su.ac.jp/~yamada/ap/queue.html SwiftでQueue さて、このリングバッファーのQueueを、Swiftでもやってみたいと思いプログラミングしてみました。 var head:Int = 0 var num:Int = 0 var max:Int = 0 var data:[Any]! var debug = false init(_ max:Int) { self.max = max self.data = Array<Any>(repeating: -1, count: max) } @discardableResult func enqueue(_ obj:Any) -> Bool { // キューが一杯だったらfalseを返す if num < max { self.data[(head + num) % max] = obj num = num + 1 return true } return false } @discardableResult func dequeue() -> Any? { if num > 0 { let obj = data[head] data[head] = -1 num = num - 1 head = (head + 1) % max; return obj } return nil } 動作確認を行うために、XCTestで次のプログラムを組んで確認してみます。 ...

公開: 2018年12月21日 · 更新: 2026年3月19日 · Toshihiko Arai