Upload
satosi-okubo
View
867
Download
0
Embed Size (px)
Citation preview
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ファイルをプロジェクトに追加します。(後述、アプリケーションバンドルファイルに加えます。)
!
補足
アプリケーションバンドルファイルは、読めるのか?
Documentsディレクトリは、重要なユーザドキュメントやアプリケーションデータファイルを保存する場合に使用します。重要なデータとは、ユーザが作成した情報で、アプリケーションで生成し直すことができないもののことです。 このディレクトリの内容は、ファイル共有によりユーザからのアクセ スが可能になります。このディレクトリの内容はiTunesによってバックアップされます。
iOSアプリケーションをビルドすると、Xcodeはアプリケーションをバンドルとしてパッケージ化します。バンドル とは、関連のあるリソースを1つの場所に集めた、ファイルシステム上のディレクトリです。iOSアプリケーションのバンドルには、アプリケーションの実行可能ファイルと支援用リソースファイル(アプリケーションアイコン、画像ファイル、ローカライズされたコンテンツなど)が含まれています。
アプリケーションバンドルファイルとは?
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
// // 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]) { // データベースファイルのコピーに失敗した場合の処理です。 } }
アプリのDocumentsフォルダのパスを取得し、DBファイル名を含めたフォルダのフルパスを取得します。
Documentsフォルダに、DBファイルが存在するかチェックし、なければアプリケーションバンドル内のDBファイルをコピーします。
ファイル
ふぁいる
※初回のみ実行される。アプリのバージョンアップ時にも、上書きされない。データは残ることに注意。
・ ・ ・ ! // 文書フォルダーに用意されたデータベースファイルを開きます。 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
DBファイルのパスを指定し、DBをオープンします。DBのハンドルを取得します。
ついでに、DBをcloseするメソッドを実装します。
※参考 Sqlite3の関数リファレンス http://www.sqlite.org/c3ref/funclist.html
作成したクラスを使い、DBのオープン・クローズを行います。
- (void)viewDidLoad { [super viewDidLoad]; sqlite3DB *sqlite3 = [sqlite3DB new]; [sqlite3 dbOpen]; [sqlite3 dbClose]; }
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; }
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に値を埋め込み実行します。
テーブルに値を入れる
-(void)finalizeSQL { if (db_) { // PREPARE済みSTATEMENTの廃棄 sqlite3_finalize(statementInsert_); } }
コンパイルしたSQLを破棄します。
作成したメソッドを使い、テーブルに値をInsertします。
- (void)viewDidLoad { [super viewDidLoad]; sqlite3DB *sqlite3 = [sqlite3DB new]; [sqlite3 dbOpen]; ! [sqlite3 prepareSQL]; [sqlite3 usersInfoInsert:1 name:@"name1"]; [sqlite3 usersInfoInsert:2 name:@"name2"]; [sqlite3 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 prepareSQL]; [sqlite3 usersInfoInsert:1 name:@"name1"]; [sqlite3 usersInfoInsert:2 name:@"name2"]; [sqlite3 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. – setBool:forKey: 2. – setFloat:forKey: 3. – setInteger:forKey: 4. – setObject:forKey: 5. – setDouble:forKey: 6. – 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"]; // NSString型として取得 NSLog(@"%d,%@",id,name);