■最終イメージ
- プロジェクトの作成
- sqliteフレームワークの追加
- fmdbライブラリの追加
- サンプルDBの作成
- 一覧画面の作成
- 詳細画面の作成
■プロジェクトの作成
iPhoneSDK:5.1
Xcodeバージョン:4.3.2
iPhoneシュミレーター:5.0.1
新規プロジェクトを作成します。
■プロジェクトにsqliteフレームワークを追加する
xCodeのトップノードを選択し、Build PhasesタブのLink Binary with Libraries欄で+ボタンを押す。
libsqlite3.0.dylibを選択してAddボタンを押す。
■プロジェクトにFMDBライブラリを追加する
以下のページでZIPボタンを押してライブラリをダウンロードします。
- fmdbライブラリダウンロードのURL
ダウンロードしたファイルを解凍してプロジェクトの適当な場所にファイルをコピーします(ここではFMDBというグループを作成してそこにコピー)。
■サンプルDBの作成
新規にデータベースを作成します。ここではLitaを使用して作成しています。
テーブルを作成します。ここではArtistという名前のテーブルを作成しています。
データを入力しておきます。
データを入力したらCompact DBボタンを押して作業を保存します。
作成されたデータベースをプロジェクトに追加します。
■一覧画面の作成
さて準備ができたのでコーディングを進めていきます。何もしていなければ以下のようにstoryboardが表示されます。
ここからViewControllerを削除します。ついでにViewController.hとViewController.mを削除します。
ViewController.hとViewController.mを削除するときに以下の確認が出ますが、Move To Trashを選んでください。
削除した後はこんな感じ。
storyboard上にNavigation Controllerを追加します。すると以下のようにNavigation ContrllerとTable View Contllerが対で追加されると思います。
Table View Contollerに対応するクラスファイルを追加します。
Subclass OfでUITableViewContollerを選択します。
Table View ContollerのクラスにMasterTableViewControllerを指定します。
ここでArtistのデータをメモリ上で格納するためArtistクラスを作成します。
Artist.h,Artist.mをそれぞれ編集します。
<Artist.h>#import@interface Artist : NSObject { NSString *id; NSString *name; NSString *genre; } @property(nonatomic,retain)NSString *id; @property(nonatomic,retain)NSString *name; @property(nonatomic,retain)NSString *genre; @end
<Artist.m>
#import "Artist.h" @implementation Artist @synthesize id; @synthesize name; @synthesize genre; @end続いてTable View Controllerを記述していきます。
<MasterTableViewController.h>
<MasterTableViewController.m>#import "FMDatabase.h" @interface MasterTableViewController : UITableViewController { NSMutableArray *mArtists; } @end
#import "MasterTableViewController.h" #import "Artist.h" @interface MasterTableViewController () @end @implementation MasterTableViewController - (id)initWithStyle:(UITableViewStyle)style { self = [super initWithStyle:style]; if (self) { // Custom initialization } return self; } - (void)viewDidLoad { [super viewDidLoad]; self.title = @"Master"; NSFileManager *fileManager = [NSFileManager defaultManager]; NSError *error; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:@"Sample.db"]; BOOL success = [fileManager fileExistsAtPath:writableDBPath]; if(!success){ NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Sample.db"]; success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error]; } if(!success){ NSAssert1(0, @"failed to create writable db file with message '%@'.", [error localizedDescription]); } FMDatabase* db = [FMDatabase databaseWithPath:writableDBPath]; if(![db open]) { NSLog(@"Err %d: %@", [db lastErrorCode], [db lastErrorMessage]); } [db setShouldCacheStatements:YES]; NSString* sql = @"SELECT * FROM Artist;"; FMResultSet* rs = [db executeQuery:sql]; mArtists = [[NSMutableArray alloc] init]; while( [rs next] ) { Artist * artist = [[Artist alloc] init]; artist.id = [rs intForColumn:@"ArtistID"]; artist.name = [rs stringForColumn:@"ArtistName"]; artist.genre = [rs stringForColumn:@"Genre"]; artist.origin = [rs stringForColumn:@"Origin"]; artist.yearsActive = [rs stringForColumn:@"YearsActive"]; [mArtists addObject:artist]; } [rs close]; [db close]; } - (void)viewDidUnload { [super viewDidUnload]; // Release any retained subviews of the main view. // e.g. self.myOutlet = nil; } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return (interfaceOrientation == UIInterfaceOrientationPortrait); } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { // Return the number of sections. return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // Return the number of rows in the section. return [mArtists count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] ; } Artist *artist = [mArtists objectAtIndex:indexPath.row]; cell.textLabel.text = artist.name; cell.detailTextLabel.text = artist.genre; cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; return cell; } /* // Override to support conditional editing of the table view. - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { // Return NO if you do not want the specified item to be editable. return YES; } */ /* // Override to support editing the table view. - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { // Delete the row from the data source [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; } else if (editingStyle == UITableViewCellEditingStyleInsert) { // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view } } */ /* // Override to support rearranging the table view. - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath { } */ /* // Override to support conditional rearranging of the table view. - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { // Return NO if you do not want the item to be re-orderable. return YES; } */ #pragma mark - Table view delegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { // Navigation logic may go here. Create and push another view controller. /* <#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:@"<#Nib name#>" bundle:nil]; // ... // Pass the selected object to the new view controller. [self.navigationController pushViewController:detailViewController animated:YES]; */ } @endここまでで実行すると以下のような画面が表示されると思います。
(まだdidSelectRowAtIndexPathメソッドは記述していません)
■詳細画面の作成
DetailViewControllerとしてクラスファイルを一つ追加し、先ほど追加したView Controllerに割り当てます。
<DetailViewController.h>
<DetailViewController.m>
DetailViewControllerを実装していきます。
#import "Artist.h" @interface DetailViewController : UIViewController { Artist *artist; UILabel *name; UILabel *genre; UILabel *origin; UILabel *yearsActive; } @property (nonatomic,retain) Artist *artist; @property (nonatomic,retain) IBOutlet UILabel *name; @property (nonatomic,retain) IBOutlet UILabel *genre; @property (nonatomic,retain) IBOutlet UILabel *origin; @property (nonatomic,retain) IBOutlet UILabel *yearsActive; @end
<DetailViewController.m>
#import "DetailViewController.h" @interface DetailViewController () @end @implementation DetailViewController @synthesize artist; @synthesize name; @synthesize genre; @synthesize origin; @synthesize yearsActive; - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } - (void)viewDidLoad { [super viewDidLoad]; name.text = artist.name; genre.text = artist.genre; origin.text = artist.origin; yearsActive.text = artist.yearsActive; } - (void)viewDidUnload { [super viewDidUnload]; // Release any retained subviews of the main view. } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return (interfaceOrientation == UIInterfaceOrientationPortrait); } @end
labelを配置し、コードのOutletとひもづけます。
DetailViewのIdentifierをDetailViewに修正します。
最後にMasterTableViewController側の呼び出し部分を記述します。
<MasterTableViewController.m> 以下の2点を追記するだけです。
#import "DetailViewController.h"
#pragma mark - Table view delegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { DetailViewController *detailViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"detailView"]; detailViewController.title = @"Detail"; detailViewController.artist = [mArtists objectAtIndex:indexPath.row]; [self.navigationController pushViewController:detailViewController animated:YES]; }できあがり
サンプルソースは以下からどうぞ。
I am Inserting a data into SQLite (using FMDB) work on device! But when I update new data ,the device does not show the new data!
返信削除Can you tell me how to solve it?
thank
You need to delete the application if you already installed your app in your device.
返信削除Because the code above copy app.db when the app.db does not exist.
Otherwise you can issue sql in appDelegate.
Hope this helps.
app.db -> Sample.db
削除I know to delete the application before "RUN" the new data would be showed ! But if I don't want to delete application, how can I do ? Can you offer the source code~
返信削除thanks
Sorry for late reply.
削除Just remove the code below and overwrite the db every time.
---------------------------------------------------------
BOOL success = [fileManager fileExistsAtPath:writableDBPath];
if(!success){
---------------------------------------------------------
とてもわかりやすい解説で参考にさせて頂いている初心者です。
返信削除手順どおりに作っていたところ、エラーが3点発生してしまいました、ご教授願えないでしょうか?
よろしくお願い致します。
MasterTableViewController.m
artist.id = [rs intForColumn:@"ArtistID"]; エラー内容① implicit conversion of 'int' to NSString is disallowed with ARC
artist.origin = [rs stringForColumn:@"Origin"];
エラー内容② Property 'origin' not found on object of type 'Artist*'
artist.yearsActive = [rs stringForColumn:@"YearsActive"];
エラー内容③ Property 'yearsActive' not found on object of type 'Artist*'
上記全て誤植でした。本文にも書きましたがソースコードをGitHubにあげたので参考にしてみてください。
削除https://github.com/tomonariokubo/SampleFMDB