Apple iPhone 3GとiPhone SDKを使ってアプリケーションを開発、公開するための情報。

ホーム / Hardware / iPhone SDK

更新:10/04/10 | iPhone SDKのDBMS SQLite3 | iPhone SDK SQLite3

まえがき

Xcodeの開発環境コンピューターの世界には様々なDBMS(DataBaseManagementSystem)が存在しています。
商用で有名なものとしてはOracle、MS-SQL、IBM DB2などがありますが、特にインターネットの世界、Webの世界ではPostgreSQL、MySQLなどが使われています。
そして、昨今注目されているのがiPhoneで採用されているSQLiteです。このページでは、SQLiteにスポットを当てて紹介を進めていきます。

SQLiteのメリット

SQLiteが何故iPhoneで採用されているのか、最大の理由は軽いという点ではないでしょうか。従来のDBMSはそれ自身が常にサービスとして起動していないとデータベースにはアクセスできませんでした。
所が、SQLiteでは必要なときにデータベースにアクセスするかのような手順で、ドライバが呼び出されて処理を実施するという方式であるためメモリやCPUに定常的な負担を与えることはありません。

デメリットとしては、きめ細やかな管理や最適化、自動的な管理機能、バックアップなどの付加的な機能、極限まで高められた高速性、大容量性などはありません。
そうした意味で、モバイルデバイスへの組み込みには最適なDBMSとも言えます。

現在では、Mac OSやRuby on Railsでも採用されて一躍脚光を浴びているようです。

iPhoneでSQLiteを使う方法

まず、手っ取り早くSQLiteの利用方法を確認する一つの方法としてサンプルアプリケーションをコードレビューする方法が挙げられます。

ADC(Apple Developper Connection)で公開されているSQLite Book Listというサンプルコードがこれに当たります。内容もシンプルなので必要最低限の機能を確認するには良い題材といえます。
ただ、SQLiteの手続きについて全く知識がないまま理解しようとすると行き詰まるので要注意です。

さて、大前提としてアプリケーションでSQLiteを利用する場合には、XcodeにてSQliteのライブラリを追加してあげる必要があります。
具体的には、libsqlite3.0.dylibというライブラリを追加してあげます。

/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.1.sdk/usr/lib/libsqlite3.0.dylib

などに存在しているはずです。
ライブラリを追加すると、このライブラリをアプリケーションから呼び出すことが出来るようになります。

データベースの初期化

データベースの初期化とは、物理的にデータベースを擁するファイルを指定してアプリケーションの稼働中に自由にアクセスできるように事前手配することです。

一般的に、ApplicationのDelegate.mの中にメソッドとして実装することになります。

iPhone:SQLite

このメソッドの中には、非常に多くの重要な要素が含まれています。

まず、SQLiteで扱われるデータベースはファイルとして実態が存在していて、これはあらかじめアプリケーションのバンドルされている必要があると言うことです。
勿論、新規にファイルを作成して、Create Database, Tableコマンドなどで作っていくことも可能ですがコストが掛かります。

Macのターミナルなどであらかじめデータベースの殻を作成して、Xcodeのパッケージに追加しておけば自動的にファイルはインストールされます。
そして、このパスの指定方法が*path=までの準備に見て取れます。

次に、準備されたpathを使って実際にデータベースをオープンする箇所です。

if (sqlite3_open([path UTF8String], &database) == SQLITE_OK) {

の部分ですが、ここにもSQLiteの特徴が現れています。
まず、[path UTF8String]とあるように、SQLiteの世界に文字列を渡す場合には、必ずUTF8StringメソッドにてChar型に変換して渡す必要があります。
これは、オブジェクトとしてのString型をC言語としてのChar型にキャストするのに近い考え方と言えます。後ほど、逆のことをするための方法も登場します。

ここでdatabaseという変数が登場します。

sqlite3 *database;

として定義されている変数で、今後ことある毎に登場する操作対象となるデータベースの代名詞となります。

sqlite3_open

はSQLite3のライブラリ関数と言うことが一目で分かります。
このように、ライブラリで用意された関数は基本的にsqlite3という文字列から始まるので見分けることも容易です。

== SQLITE_OK

を見れば、SQLITE_OKもまた事前定義された固定値の代名詞であることが分かります。同時にopen(DBの準備)がOK(成功)したら……という条件式になっていることが分かります。

先に失敗した場合のコードを見てみます。

} else {
sqlite3_close(database);
NSAssert1(0,@"error %@",sqlite3_errmsg(database));
}

sqlite3_closeはその名の通りクローズ(閉じる)命令です。
NSAssert1は、デバッグウィンドウに文字列を表示する関数で、sqlite3_errmsg(database)を引数にして実際に発生したエラーメッセージを表示させようとしています。問題がない場合にはメッセージはやはり「問題はありませんでした」といった内容の英文になります。

注意点としてはNSAssert1の後は基本的に正常にプログラムは処理を継続しません。半ば経験則ですが、NSAssert1を踏んだときにはいったんエミュレーターを終了してデバッグ後に再起動しましょう。

話しのついでですが、一般的にデバッグウィンドウに任意の文字を表示して処理も継続したい場合にはNSLog();関数を利用します。引数には文字列を取りますので、数字などを表示させる場合にはちょっと面倒ですが……。

さて、話しを元に戻してDB準備に成功した場合のルーチンを見ていきます。
ここで最も重要なポイントは、

const char *sql = "SELECT pk FROM account";
sqlite3_stmt *statement;

if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL) == SQLITE_OK){

while (sqlite3_step(statement) == SQLITE_ROW) {
……

sqlite3_finalize(statement);

の部分です。
DB準備には成功しているので、早速SQL文の実行に移るわけですがSQL文をconst charにて用意しています。NSStringといったオブジェクト型の文字列ではなくて、const charを用いることで高速化を図っているようです。

また、sqlite3_prepare_v2関数によってSQL文をsqlite3_stmt型のstatementに準備するという手続きもSQLite固有の特徴といえます。
このstatementの準備が出来ると、初めてsqlite3_step(statement)にて処理を実行することが出来ます。ただし、この場合はSelect文の例となっていますが見ての通り結果は行単位で取り出されるためwhile文などで行を進める処理を実装する必要があることもしばしばです。

Select文の例では、取り出した行の値をObjective-Cのオブジェクトに代入して初めて目的を達したことになります。

int primaryKey = sqlite3_column_int(statement, 0);

がその部分です。
ここではInteger型のため見た目がスッキリしています。
基本的にはsqlite3_column_intのような取り出すための関数が各型毎に用意されています。

最後に決して忘れてはいけないのが、

sqlite3_finalize(statement);

です。DBをCloseする前にはsqlite3_prepare_v2で準備手順を通したステートメントを全てsqlite3_finalize関数にて破棄しておく必要があります。
これをしておかないと、DBをクローズすることは出来ません。(エンバグ)

毎処理毎に破棄する必要はなく、アプリケーションが終了するまで利用するようなステートメントは、

- (void)applicationDidFinishLaunching:(UIApplication *)application {

メソッドの中でファイナライズする方が高速でスマートです。
通常、アプリケーションの中では複数のステートメントを扱うことになるため、ファイナライズ処理は次のように一つのクラスメソッドにまとめるのが流儀のようです。

+ (void)finalizeStatements {
if (init_records) sqlite3_finalize(init_records);
if (count_statement) sqlite3_finalize(count_statement);
if (check_duplication_statement) sqlite3_finalize(check_duplication_statement);
if (get_sql_value_statement) sqlite3_finalize(get_sql_value_statement);
}



 

 
コメント・フィードバック
ダウンロード
ストリーミング関連
Macintosh関連
Windows関連
メディアなど
 
ハードウェア
ソフトウェア/サービス/開発SDK
デジタル一眼レフカメラ
趣味関連
ゲーム 〜楽しいゲームの紹介や攻略法
RoverMNI(ローバーミニ) 
雑記
その他
Copyright (c)1998-2016 CNXGROUP All Rights Reserved.
このページの全部あるいは一部を無断で利用(コピー)することを禁じます。
>