iOSハンズオントレーニング
データの永続化(SQLite3, NSUserDefaults)

 大久保 聡
SQLite3
アプリ組み込み用の軽量RDB
トランザクション

ビュー

トリガー
使ってみる
SQLiteはターミナルから起動します。ター
ミナルを起動し、sqlite3と叩きます。

.helpと叩いてみよう。
終了させます。.quitと叩いてみよう。
DBを作ってみる
DBを利用するには、まずDBファイルを作り、その中にさらに
データの入れ物にあたるテーブル(表)を作成します。	

DBのファイルを作るには、さっきのsqlite3に引数でファイル名を
渡して起動することで、DBファイルが作成されます。	

DBファイル名は、twitterDB.sqliteとしておきます。ターミナルで
「sqlite3 sampleDB.sqlite」と叩きます。

「.database」と叩き、作成されたDBを確認します。
テーブルを作ってみる
次のDDL(Data定義文)をそのまま叩きます。
CREATE TABLE userinfo (!
'ID' integer,!
'name' text!
);

「.schema」と叩き、テーブルを確認します。
SQLiteの組み込み
xCodeのプロジェクトを開き、SQLite3のライブラリ参照を追加し
ます。

※ベースとなるプロジェクトをダウンロードしてください。

https:/
/github.com/ovjang/NoUseStoryBoard
DBファイルの追加
先ほど作成した、SQLiteのDBファイルをプロジェクトに追加します。(後述、アプリケーションバンドルファイルに加えます。)	


!
補足
アプリケーションバンドルファイルとは?	


iOSアプリケーションをビルドすると、Xcodeはアプリケーションをバンドルとしてパッケージ化します。バンドル とは、関連の
あるリソースを1つの場所に集めた、ファイルシステム上のディレクトリです。iOSアプリケーションのバンドルには、アプリケー
ションの実行可能ファイルと支援用リソースファイル(アプリケーションアイコン、画像ファイル、ローカライズされたコンテン
ツなど)が含まれています。

アプリケーションバンドルファイルは、読めるのか?	


Documentsディレクトリは、重要なユーザドキュメントやアプリケー
ションデータファイルを保存する場合に使用します。重要なデータと
は、ユーザが作成した情報で、アプリケーションで生成し直すことが
できないもののことです。

このディレクトリの内容は、ファイル共有によりユーザからのアクセ

スが可能になります。このディレクトリの内容はiTunesによってバッ
クアップされます。

Libraryディレクトリの配下には、設定ファイルなどを格納します。

Library/Preferencesの配下に、NSUserDefaultsの情報もここに保存さ
れます。
DBのオープンクローズ
新規にクラスを作成します。	

sqlite3.hのインクルードします。	

dbのハンドルを格納する、メンバ変数を定義します。
//
//
//

sqlite3DB.h

!

#import <Foundation/Foundation.h>
#import <sqlite3.h>

!

@interface sqlite3DB : NSObject {
sqlite3* db_;
}

!

-(void)dbOpen;
-(void)dbClose;

!

@end
アプリのDocumentsフォルダのパスを取得し、DBファイル名を含めたフォルダのフルパスを取得します。	

Documentsフォルダに、DBファイルが存在するかチェックし、なければアプリケーションバンドル内のDB
ファイルをコピーします。	

ファイル	

ふぁいる

※初回のみ実行される。アプリのバージョンアップ時にも、上書きされない。データは残ることに注意。
//
//
//

sqlite3DB.m

!
#import "sqlite3DB.h"
!
@implementation sqlite3DB
!

-(void)dbOpen {
// データベースファイルを格納するために、Documentsフォルダーを取得します。
NSString* docs_path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES) objectAtIndex:0];
// データベースファイルのパスを取得します。
NSString* database_path = [NSString stringWithFormat:@"%@/%@", docs_path, @"sampleDB.sqlite"];
// Documentsフォルダーにデータベースファイルが存在しているかを確認します。

!

NSFileManager* manager = [NSFileManager defaultManager];
if (![manager fileExistsAtPath:database_path])
{
NSError* error = nil;
// Documentsフォルダーに存在しない場合は、データベースの複製元をバンドルから取得します。
NSString* template_path = [[[NSBundle mainBundle] resourcePath]
stringByAppendingPathComponent:database_filename];
// アプリケーションバンドルから取得したデータベースファイルを文書フォルダーにコピーします。
if (![manager copyItemAtPath:template_path toPath:database_path error:&error])
{
// データベースファイルのコピーに失敗した場合の処理です。
}
}
DBファイルのパスを指定し、DBをオープンします。DBのハンドルを取
得します。	

ついでに、DBをcloseするメソッドを実装します。
  ・
  ・
  ・

!

// 文書フォルダーに用意されたデータベースファイルを開きます。
if (sqlite3_open([database_path UTF8String], &db_) != SQLITE_OK)
{
// データベースファイルを SQLite で開くことに失敗しました。
}

}

!
!

-(void)dbClose {
NSLog(@"DB Close");
if (db_) {
// DB Close
sqlite3_close(db_);
}
db_ = nil;
}
@end

※参考 Sqlite3の関数リファレンス http:/
/www.sqlite.org/c3ref/funclist.html
作成したクラスを使い、DBのオープン・クローズを行います。
- (void)viewDidLoad
{
[super viewDidLoad];
sqlite3DB *sqlite3 = [sqlite3DB new];
[sqlite3 dbOpen];
[sqlite3 dbClose];
}
テーブルに値を入れる
SQLを作成し、事前にコンパイルしておきます。
sqlite3_stmt* statementInsert_;

!

-(BOOL)prepareSQL {
// SQL文
NSString* insertSQL

= @"insert into userinfo values (?, ?)";

// SQLのコンパイル
if(sqlite3_prepare_v2(db_, [insertSQL UTF8String], -1, &statementInsert_, NULL) != SQLITE_OK)
{
NSLog( @"Failed to prepare statement with '%s'.", sqlite3_errmsg( db_ ));
return NO;
}
return YES;
}

コンパイルしたSQLに値を埋め込み実行します。
-(BOOL)usersInfoInsert:(int)id name:(NSString*)name {
// バインド変数のリセット
sqlite3_reset(statementInsert_);
// バインド変数に値のセット
sqlite3_bind_int(statementInsert_, 1, id);
sqlite3_bind_text(statementInsert_, 2, [name UTF8String], -1, SQLITE_TRANSIENT);
// SQL実行
int wasSucceeded = sqlite3_step(statementInsert_);
if( wasSucceeded != SQLITE_DONE ) {
NSLog( @"Failed to insert from database with '%s'.", sqlite3_errmsg( db_ ));
return NO;
}
return YES;
}
コンパイルしたSQLを破棄します。
-(void)finalizeSQL {
if (db_) {
// PREPARE済みSTATEMENTの廃棄
sqlite3_finalize(statementInsert_);
}
}

作成したメソッドを使い、テーブルに値をInsertします。
- (void)viewDidLoad
{
[super viewDidLoad];
sqlite3DB *sqlite3 = [sqlite3DB new];
[sqlite3 dbOpen];

!
!
}

[sqlite3
[sqlite3
[sqlite3
[sqlite3

prepareSQL];
usersInfoInsert:1 name:@"name1"];
usersInfoInsert:2 name:@"name2"];
finalizeSQL];

[sqlite3 dbClose];
テーブルの中身を参照する
-(void)userInfoSelect {
// 発行するSQL
NSString* selectSQL = [NSString stringWithFormat:@"select * from userinfo"];
// SQLのコンパイル
sqlite3_stmt *statement = nil;
if(sqlite3_prepare_v2(db_, [selectSQL UTF8String], -1, &statement, NULL) == SQLITE_OK) {
@try {
int wasSucceeded = 0;
// 次の行が存在する時、戻り値はSQLITE_ROWを返却する。ないとき、SQLITE_DONEを返却する。
do
{
// SQLの実行(1行読み込み)
wasSucceeded = sqlite3_step(statement);
if (wasSucceeded == SQLITE_ROW)
{
// 中身の読み取り
NSLog(@"%d,%@",
(int)sqlite3_column_int(statement, 0),
[NSString stringWithUTF8String:(char*)sqlite3_column_text(statement, 1)]
);
} else if(wasSucceeded == SQLITE_DONE) {
//読み切り
} else {
return;
}
} while (wasSucceeded == SQLITE_ROW);
}
@finally {
// PREPARE済みSTATEMENTの廃棄
sqlite3_finalize(statement);
}
} else {
// PREPARE失敗
return;
}
return;
}
作成したメソッドを使い、テーブルをSelectします。
- (void)viewDidLoad
{
[super viewDidLoad];
sqlite3DB *sqlite3 = [sqlite3DB new];
[sqlite3 dbOpen];

!

[sqlite3
[sqlite3
[sqlite3
[sqlite3

prepareSQL];
usersInfoInsert:1 name:@"name1"];
usersInfoInsert:2 name:@"name2"];
finalizeSQL];

[sqlite3 userInfoSelect];
[sqlite3 dbClose];
}
NSUserDefaults
設定情報などを、保存する用途に使う
書き込み、読み込み、削除の操作ができる

型ごとに操作のメソッドがある。
読み書きのメソッド
Getting Default Values
1. – arrayForKey:
2. – boolForKey:
3. – dataForKey:
4. – dictionaryForKey:
5. – floatForKey:
6. – integerForKey:
7. – objectForKey:
8. – stringArrayForKey:
9. – stringForKey:
10. – doubleForKey:
11. – URLForKey:

Setting Default Values
1.
2.
3.
4.
5.
6.

– setBool:forKey:
– setFloat:forKey:
– setInteger:forKey:
– setObject:forKey:
– setDouble:forKey:
– setURL:forKey:

Removing Defaults

1. – removeObjectForKey:
NSUserDefaultsの使い方
// UserDefaultsの取得

!

NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];

// 取得

// NSUserDefaultsに保存・更新する
[userDefault setInteger:1 forKey:@"ID"];

// int型

[userDefault setObject:@"NAME1" forKey:@"NAME"];

// Object型

// NSUserDefaultsからデータを読み込む
int id = [userDefault integerForKey:@"ID"];

// int型として取得

NSString* name = [userDefault stringForKey:@"NAME"];
NSLog(@"%d,%@",id,name);

// NSString型として取得

iOSハンズオントレーニング データの永続化編(SQLite3, NSUserDefaults)