FMDBで簡単写真アルバムを作ろう Part.5 ~【iPhone】SQLiteのデータを出し入れするためのクラスをつくる~

前回:FMDBで簡単写真アルバムを作ろう Part.4 ~NavigationBarと画面遷移~

簡単写真アルバムのソースコードGitHubからどうぞ
ー>https://github.com/ics-hiro/SelfPhotoLibrary

前回ではNewViewControllerの画面を作りました。

今回はデータベースとのやり取りをするためのクラスを作りたいと思います。


このアプリの核はデータベースを使ったデータのやり取りにあります。
そしてデータはViewController,NewViewController,PhotoViewControllerのいずれでも使用することになります。

データベースとやりとりするコードは、UIViewController内に混在させる書き方と、
別クラスにするやり方があります。


今回はコード全体の見通しを良くするために、データベース関連は別クラスで作成することにしました。

DataModelsという名前のクラスをNSObjectのサブクラスで作成する

まず、DataModels.hとDataModels.mをNSObjectのサブクラスとして作成します。
これは前々回を参照してください。

データベースの操作に必要な機能を書き出そう

データベースの構造はPart.1でも解説しましたが、そのときに使った画像を再びお見せします。

必要な操作を箇条書きにすると、

  • SQLiteデータベースをつくる(SelfPhoto.sqlite
  • テーブルをつくる(Libraryという名前のテーブル)
  • データを挿入する(メモであるtitle,画像であるcontents)
  • データを取り出してくる(titile,contetnsそれぞれ)
  • テーブルを空っぽにする(今回だけの少し特別な操作かも)

DataModelsのソースコード全体

まずはDataModelsのhファイルとmファイルのコードを全部書いておきます。
これはGitHubから見ることもダウンロードすることもできます。

DataModels.h

#import <Foundation/Foundation.h>

@interface DataModels : NSObject
+ (void)insertTitle:(NSString *)title Contents:(NSData *)contents;
+ (NSMutableArray *)selectTitle:(NSMutableArray *)array;
+ (NSMutableArray *)selectContents:(NSMutableArray *)array;
+ (void)drop_table;
@end

DataModels.m

#import "DataModels.h"
#import "FMDatabase.h"
#import "FMResultSet.h"

// データベースの名前
#define DB_FILE_NAME @"SelfPhoto.sqlite"

// データベースの処理
#define SQL_CREATE @"CREATE TABLE IF NOT EXISTS Library (id INTEGER PRIMARY KEY AUTOINCREMENT,title TEXT,contents BLOB)"
#define SQL_INSERT @"INSERT INTO Library (title,contents) VALUES (?,?)"
#define SQL_SELECT @"SELECT * FROM Library ORDER BY id DESC"
#define SQL_DROPTABLE @"DELETE FROM Library"

@interface DataModels ()

@end

@implementation DataModels

// タイトルと画像の挿入
+ (void)insertTitle:(NSString *)title Contents:(NSData *)contents
{
    NSArray*    paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES );
    NSString*   dir   = [paths objectAtIndex:0];
    FMDatabase* db    = [FMDatabase databaseWithPath:[dir stringByAppendingPathComponent:DB_FILE_NAME]];
    
    
    [db open];
    [db executeUpdate:SQL_CREATE];
    [db executeUpdate:SQL_INSERT,title,contents];
    [db close];
}

// タイトルの取り出し
+ (NSMutableArray *)selectTitle :(NSMutableArray *)array
{
    NSArray*    paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES );
    NSString*   dir   = [paths objectAtIndex:0];
    FMDatabase* db    = [FMDatabase databaseWithPath:[dir stringByAppendingPathComponent:DB_FILE_NAME]];
    [db open];
    
	
    FMResultSet*    results = [db executeQuery:SQL_SELECT];
    
    NSString*       titleData;
	
    while( [results next] )
    {
	titleData = [results stringForColumn:@"title"];
        [array addObject:titleData];
    }
	
    [db close];
	
    return array;
}

// 画像の取り出し
+ (NSMutableArray *)selectContents :(NSMutableArray *)array
{
    NSArray*    paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES );
    NSString*   dir   = [paths objectAtIndex:0];
    FMDatabase* db    = [FMDatabase databaseWithPath:[dir stringByAppendingPathComponent:DB_FILE_NAME]];
    
    [db open];
	
    FMResultSet*    results = [db executeQuery:SQL_SELECT];
    
    NSData*       contentsData;
	
    while( [results next] )
    {
	contentsData = [results dataForColumn:@"contents"];
        [array addObject:contentsData];
    }
	
    [db close];
	
    return array;
}

// テーブルを空っぽにする
+ (void)drop_table
{
    NSArray*    paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES );
    NSString*   dir   = [paths objectAtIndex:0];
    FMDatabase* db    = [FMDatabase databaseWithPath:[dir stringByAppendingPathComponent:DB_FILE_NAME]];
    
    
    [db open];
    [db executeUpdate:SQL_DROPTABLE];
    [db close];
}

@end

SQLiteファイルを作成する

SQLiteファイルはこの部分で生成されます。

    NSArray*    paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES );
    NSString*   dir   = [paths objectAtIndex:0];
    FMDatabase* db    = [FMDatabase databaseWithPath:[dir stringByAppendingPathComponent:DB_FILE_NAME]];

ファイルがすでに存在しているなら参照(メモと画像を最初保存するときに、SelfPhoto.sqliteがつくられます。それ以後はこのSQLiteファイルでデータの出し入れがなされます)、なければ新規作成(最初にアプリを立ち上げたとき、SQLiteファイルはありません。このコードが書かれたメソッドが初めて呼ばれたときに生成されます)し、そこに接続されたFMDatabase のインスタンスを返します。

「検索日記」のソースコードでも同じ部分があり、そこでも同様の解説をしているので、
こちらもご参照ください。
ー>http://d.hatena.ne.jp/kazukingband/20120520/1337463651

今回はそれぞれのメソッドでこのコードを書いておりくどくなっていますが、わかりやすさ重視です。

データを挿入する

データを挿入するメソッドはこれです。

// タイトルと画像の挿入
+ (void)insertTitle:(NSString *)title Contents:(NSData *)contents
{
    NSArray*    paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES );
    NSString*   dir   = [paths objectAtIndex:0];
    FMDatabase* db    = [FMDatabase databaseWithPath:[dir stringByAppendingPathComponent:DB_FILE_NAME]];
    
    
    [db open];
    [db executeUpdate:SQL_CREATE];
    [db executeUpdate:SQL_INSERT,title,contents];
    [db close];
}

データを挿入するときにはじめてLibraryテーブルを作成しています。

このメソッドは引数を2つ受け取っています。
NSString型のtitleという名前の引数と、NSData型のcontentsという名前の引数です。

NewViewControllerからタイトルのNSStringと画像のNSDataを受け取って、ここで処理しています。

FMDBにおけるSQL文がどうなっているかをこのSQL_INSERTを例に図示します。

#defineで定義したSQL_INSERTの「?」、つまりパラメータにtitle,contentsという引数を入れています。順番に入ります。
title,contentsはともにカラム(フィールド)名でもありますが、混同しないでください。

title,contentsカラムにいれるデータなので、引数の名前もtitle,contentsにしただけのことです。
実際、引数の名前はなんでもよいです。


データを取り出す

タイトルを取り出すコードは

// タイトルの取り出し
+ (NSMutableArray *)selectTitle :(NSMutableArray *)array
{
    NSArray*    paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES );
    NSString*   dir   = [paths objectAtIndex:0];
    FMDatabase* db    = [FMDatabase databaseWithPath:[dir stringByAppendingPathComponent:DB_FILE_NAME]];
    [db open];
    
	
    FMResultSet*    results = [db executeQuery:SQL_SELECT];
    
    NSString*       titleData;
	
    while( [results next] )
    {
	titleData = [results stringForColumn:@"title"]; //titleカラムを取り出す
        [array addObject:titleData];
    }
	
    [db close];
	
    return array;
}

画像を取り出すコードは

// 画像の取り出し
+ (NSMutableArray *)selectContents :(NSMutableArray *)array
{
    NSArray*    paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES );
    NSString*   dir   = [paths objectAtIndex:0];
    FMDatabase* db    = [FMDatabase databaseWithPath:[dir stringByAppendingPathComponent:DB_FILE_NAME]];
    
    [db open];
	
    FMResultSet*    results = [db executeQuery:SQL_SELECT];
    
    NSData*       contentsData;
	
    while( [results next] )
    {
	contentsData = [results dataForColumn:@"contents"]; //contentsカラムを取り出す
        [array addObject:contentsData];
    }
	
    [db close];
	
    return array;
}
  • 「SELECT * FROM Library ORDER BY id DESC」でLibraryテーブルからidを逆順にしてデータを取り出す。
  • そして自分が必要とするカラムの名前をしていし、配列に格納。
  • そのときのデータをどんどんaddしていくから、可変配列をつかう(NSMutableArray)

while([results next])はresultsに入ってるものをどんどん取り出していき、中身がなくなったらnilを返す

arrayは引数の名前。


テーブルを空っぽにする

テーブルを空っぽにするコードは

// テーブルを空っぽにする
+ (void)drop_table
{
    NSArray*    paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES );
    NSString*   dir   = [paths objectAtIndex:0];
    FMDatabase* db    = [FMDatabase databaseWithPath:[dir stringByAppendingPathComponent:DB_FILE_NAME]];
    
    
    [db open];
    [db executeUpdate:SQL_DROPTABLE];
    [db close];
}

「DELETE FROM Library」を実行するというコードですね。



これらはすべてクラスメソッドです。

DataModelsのインスタンスをつくらずにスパン!と使えるのでクラスメソッドにしました。

次回は実際にDataModelsのクラスメソッドを使って、NewViewControllerを実装しましょう。


簡単写真アルバムアプリ記事一覧
FMDBで簡単写真アルバムを作ろう Part.1 ~メモが書ける写真アルバムをつくる~
FMDBで簡単写真アルバムを作ろう Part.2 ~Xcode4.3,SingleViewApplication,FMDB準備~
FMDBで簡単写真アルバムを作ろう Part.3 ~必要なファイルを追加して整理しよう~
FMDBで簡単写真アルバムを作ろう Part.4 ~NavigationBarと画面遷移~
FMDBで簡単写真アルバムを作ろう Part.5 ~【iPhone】SQLiteのデータを出し入れするためのクラスをつくる~
FMDBで簡単写真アルバムを作ろう Part.6 ~【iPhone】UITextField,UIActionSheet,UIImagePickerControllerとメモ、写真の保存~
FMDBで簡単写真アルバムを作ろう Part.7 ~【iPhone】SQLiteのデータを取り出してTableViewに表示~
FMDBで簡単写真アルバムを作ろう Part.8 ~【iPhone】TableViewの画面遷移、異なるView間での値の受け渡し~
FMDBで簡単写真アルバムを作ろう Part.9 ~【iPhone】TableViewのセルを削除、commitEditingStyle ~
FMDBで簡単写真アルバムを作ろう 最終章 ~簡単写真アルバムの完成~

======================
当ブログ管理人のツイッターこちら
◎フォローしてくださると泣いて喜びます!ツイッター上で当ブログの質問などにもできるだけお答えしますし、役に立つiPhoneアプリ開発情報もつぶやきます。個人的なご依頼(たとえば、プログラミングの家庭教師、Skypeレッスンをしてくれないか、iPhoneアプリ開発の勉強会ってやってるの、とかですね)でもかまいません。
スカイプレッスンについて
開発をしているとその都度ぶつかる問題があると思いますが、検索で調べてもなかなかわからない、あるいは調べても非常に時間がかかる場合があると思います。開発者のみなさんもお忙しいと思いますので、私のレッスンを受けながら開発を進めていただけると、大幅にお時間を短縮できます。加えて、iPhoneアプリ開発の基礎、応用が身につき、今後の開発もスムーズに進められます

お問い合わせはツイッター、またはhiyoshimarukoアットマークgmail.comまでお願いします。(アットマークを@にしてください)お待ちしております!