iPhone Appのサンプルコード SQLiteBooksのソースを読む - 2.アプリケーション起動時のDB読み込み
アプリケーション起動時にDBからデータを読み込んでいる部分のソースを確認する。
AppDelegateのinitializeDatabaseメソッド
applicationDidFinishLaunchingメソッドの中から呼ばれているinitializeDatabaseメソッドは何をやっているのか?
DB(bookdb.sql)に接続し、取得したデータをself.booksに格納しているようだ。
アプリケーションの起動時にbooksにデータを読み込み、MasterViewControllerでbooksからデータを取得し画面に表示しているようだ。
AppDelegate.m
// Open the database connection and retrieve minimal information for all objects. - (void)initializeDatabase { NSMutableArray *bookArray = [[NSMutableArray alloc] init]; self.books = bookArray; [bookArray release]; // The database is stored in the application bundle. NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *path = [documentsDirectory stringByAppendingPathComponent:@"bookdb.sql"]; // Open the database. The database was prepared outside the application. if (sqlite3_open([path UTF8String], &database) == SQLITE_OK) { // Get the primary key for all books. const char *sql = "SELECT pk FROM book"; sqlite3_stmt *statement; // Preparing a statement compiles the SQL query into a byte-code program in the SQLite library. // The third parameter is either the length of the SQL string or -1 to read up to the first null terminator. if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL) == SQLITE_OK) { // We "step" through the results - once for each row. while (sqlite3_step(statement) == SQLITE_ROW) { // The second parameter indicates the column index into the result set. int primaryKey = sqlite3_column_int(statement, 0); // We avoid the alloc-init-autorelease pattern here because we are in a tight loop and // autorelease is slightly more expensive than release. This design choice has nothing to do with // actual memory management - at the end of this block of code, all the book objects allocated // here will be in memory regardless of whether we use autorelease or release, because they are // retained by the books array. Book *book = [[Book alloc] initWithPrimaryKey:primaryKey database:database]; [books addObject:book]; [book release]; } } // "Finalize" the statement - releases the resources associated with the statement. sqlite3_finalize(statement); } else { // Even though the open failed, call close to properly clean up resources. sqlite3_close(database); NSAssert1(0, @"Failed to open database with message '%s'.", sqlite3_errmsg(database)); // Additional error handling, as appropriate... } }
MasterViewController.m
ここでbooksからタイトルを取得し一覧のcell.textに設定している。
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"MyIdentifier"]; if (cell == nil) { // Create a new cell. CGRectZero allows the cell to determine the appropriate size. cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"MyIdentifier"] autorelease]; } // Retrieve the book object matching the row from the application delegate's array. AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; Book *book = (Book *)[appDelegate.books objectAtIndex:indexPath.row]; cell.text = book.title; return cell; }
下記のようのデバッグ文を追加し動きを見てみる
AppDelegate.m
// Open the database connection and retrieve minimal information for all objects. - (void)initializeDatabase { NSLog(@"AppDelegate#initializeDatabase"); // デバッグ文 NSMutableArray *bookArray = [[NSMutableArray alloc] init]; self.books = bookArray; [bookArray release]; // The database is stored in the application bundle. NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *path = [documentsDirectory stringByAppendingPathComponent:@"bookdb.sql"]; NSLog(@"path : %@",path); // デバッグ文 // Open the database. The database was prepared outside the application. if (sqlite3_open([path UTF8String], &database) == SQLITE_OK) { // Get the primary key for all books. const char *sql = "SELECT pk FROM book"; sqlite3_stmt *statement; // Preparing a statement compiles the SQL query into a byte-code program in the SQLite library. // The third parameter is either the length of the SQL string or -1 to read up to the first null terminator. if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL) == SQLITE_OK) { // We "step" through the results - once for each row. while (sqlite3_step(statement) == SQLITE_ROW) { // The second parameter indicates the column index into the result set. int primaryKey = sqlite3_column_int(statement, 0); NSLog(@"primaryKey : %d",primaryKey); // デバッグ文 // We avoid the alloc-init-autorelease pattern here because we are in a tight loop and // autorelease is slightly more expensive than release. This design choice has nothing to do with // actual memory management - at the end of this block of code, all the book objects allocated // here will be in memory regardless of whether we use autorelease or release, because they are // retained by the books array. Book *book = [[Book alloc] initWithPrimaryKey:primaryKey database:database]; NSLog(@"===================="); // デバッグ文 NSLog(@"book.primaryKey : %d",book.primaryKey); // デバッグ文 NSLog(@"book.title : %@",book.title); // デバッグ文 NSLog(@"book.copyright : %@",book.copyright); // デバッグ文 NSLog(@"book.copyright : %@",book.author); // デバッグ文 [books addObject:book]; [book release]; } } // "Finalize" the statement - releases the resources associated with the statement. sqlite3_finalize(statement); } else { // Even though the open failed, call close to properly clean up resources. sqlite3_close(database); NSAssert1(0, @"Failed to open database with message '%s'.", sqlite3_errmsg(database)); // Additional error handling, as appropriate... } }
MasterViewController.m
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSLog(@"MasterViewController#tableView cellForRowAtIndexPath"); // デバッグ文 UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"MyIdentifier"]; if (cell == nil) { // Create a new cell. CGRectZero allows the cell to determine the appropriate size. cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"MyIdentifier"] autorelease]; } // Retrieve the book object matching the row from the application delegate's array. AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; Book *book = (Book *)[appDelegate.books objectAtIndex:indexPath.row]; NSLog(@"book.title : %@",book.title); // デバッグ文 cell.text = book.title; return cell; }
アプリケーション起動後のスクリーンショット
デバッグコンソールの出力
思ったとおりの動作になっていることを確認できた。
2008-11-30 18:59:56.598 SQLiteBooks[27063:20b] AppDelegate#initializeDatabase 2008-11-30 18:59:56.598 SQLiteBooks[27063:20b] path : /Users/kuru/Library/Application Support/iPhone Simulator/User/Applications/8CD7D8A9-8B28-4A56-A507-20639F4CDA5E/Documents/bookdb.sql 2008-11-30 18:59:56.602 SQLiteBooks[27063:20b] primaryKey : 1 2008-11-30 18:59:56.602 SQLiteBooks[27063:20b] ==================== 2008-11-30 18:59:56.603 SQLiteBooks[27063:20b] book.primaryKey : 1 2008-11-30 18:59:56.603 SQLiteBooks[27063:20b] book.title : War and Peace 2008-11-30 18:59:56.603 SQLiteBooks[27063:20b] book.copyright : (null) 2008-11-30 18:59:56.604 SQLiteBooks[27063:20b] book.copyright : (null) 2008-11-30 18:59:56.605 SQLiteBooks[27063:20b] primaryKey : 2 2008-11-30 18:59:56.607 SQLiteBooks[27063:20b] ==================== 2008-11-30 18:59:56.607 SQLiteBooks[27063:20b] book.primaryKey : 2 2008-11-30 18:59:56.608 SQLiteBooks[27063:20b] book.title : Mac OS X Internals 2008-11-30 18:59:56.609 SQLiteBooks[27063:20b] book.copyright : (null) 2008-11-30 18:59:56.612 SQLiteBooks[27063:20b] book.copyright : (null) 2008-11-30 18:59:56.616 SQLiteBooks[27063:20b] primaryKey : 3 2008-11-30 18:59:56.616 SQLiteBooks[27063:20b] ==================== 2008-11-30 18:59:56.616 SQLiteBooks[27063:20b] book.primaryKey : 3 2008-11-30 18:59:56.617 SQLiteBooks[27063:20b] book.title : The Divine Comedy 2008-11-30 18:59:56.617 SQLiteBooks[27063:20b] book.copyright : (null) 2008-11-30 18:59:56.617 SQLiteBooks[27063:20b] book.copyright : (null) 2008-11-30 18:59:56.621 SQLiteBooks[27063:20b] MasterViewController#tableView cellForRowAtIndexPath 2008-11-30 18:59:56.622 SQLiteBooks[27063:20b] book.title : The Divine Comedy 2008-11-30 18:59:56.647 SQLiteBooks[27063:20b] MasterViewController#tableView cellForRowAtIndexPath 2008-11-30 18:59:56.648 SQLiteBooks[27063:20b] book.title : Mac OS X Internals 2008-11-30 18:59:56.649 SQLiteBooks[27063:20b] MasterViewController#tableView cellForRowAtIndexPath 2008-11-30 18:59:56.649 SQLiteBooks[27063:20b] book.title : War and Peace
次は入力したデータを保存する動作を確認する。