誰だってそーする。俺もそーする。
最後に残ったのが保守作業。
極端な話、猿のようにゲームやられてそれを全部記録してたら、iPhoneが破裂しちゃうわけですよ。ま、今回程度の記録なら1件につき100バイトくらいとして、1万件記録しても1MBだけどね。
容量制限はつけるのが仁義ってもんよ。
なので、一定サイズ以上にならないように日付の古いものは削除するようにします。
このために使うSQL文が「iPhoneアプリ開発、その(78)」で使った
と
になるわけですわ。
まずは、ちゃんと保守できているか確認するために、今登録されている結果をすべて表示するメソッドを用意してみるっすよ~。
- (void)dumpResults
使うSQL文自体は単純ですわ。
datetimeを大きい順に並べてるのは、最新の日付が上に表示されるようにするため。
めんどくさかったのが、取り出したdouble型のdatetimeをどうやって2009年5月14日 00:50:13といったような表示にするかってところ。
これには、またまたSQLiteBooksのソースのお世話になりました。Book.hで宣言されているcopyrightが日付なんですが、このNSDate*型の変数を画面上ではちゃんと日付で表示してるわけですよ。
さっそく編集>検索>プロジェクト内で検索メニューで出てくる検索ダイアログにcopyrightと打ち込んで検索。DetailViewController.mのtableView:cellForRowAtIndexPath:てメソッドでNSStringに変換してました。
てやつです。
んじゃ、このdateFormatterってなによ?て同一ソース内を検索すると
て感じで準備されてます。NSDateFormatterね。なんでしょ?
困った時は右クリック(iPhoneアプリ開発、その(33)参照)だ。ちなみにオプションキー+クリックという手もある。
出てきたNSDateFormatterの説明を読んでいくと、stringFromDateメソッドが受け取ったNSDateインスタンスの内容を元に、setDateStyleやsetTimeStyleで指定された形式で日付文字列としてNSStringインスタンスを作るメソッドだってのがわかるわけです。
同じように、double型からNSDateインスタンスを作るのはSQLiteBooksのBook.mのhydrateメソッドからNSDateのdateWithTimeIntervalSince1970メソッドを使えばいい(でも、なんでSine1970と思った人はunix 1970でググりましょう)ってのがわかるので、これで必要なクラスとメソッドがそろったことになる。
今回は秒数も表示したいのでsetTimeStyleにはNSDateFormatterNoStyleではなくNSDateFormatterMediumStyleを指定します。他にkCFDateFormatterFullStyleとかkCFDateFormatterShortStyleとかもあるんで、各自ソースを変更していろいろ試してみましょう。とくに日付の方はkCFDateFormatterFullStyleだとiPhone(エミューレター)側の設定>一般>言語環境>書式で選んだ言語によって変化が大きいっす。
あと、printfはNSString*を受け付けないのでC文字列にする必要があるんですが、それにはNSStringのcStringUsingEncodingメソッドを使います。ここらへんはAPIリファレンスをこつこつ調査ね。引数で指定するエンコーディングはNSUTF8StringEncodingでした。こっちは力技。NSShiftJISStringEncodingとかNSJapaneseEUCStringEncodingとか指定して試してみた。まあねえprintfの段階でUTF-16やUTF-32は消えるわけで、今更Shift JISやEUCでもないしね~。
つか、ソースのエンコードをUTF-8にしてるから、日本語普通に使えるんじゃね~か。コンソール。今気づいたわ~。ぬかった~。
実装終わったら、前回のdbAppDelegate.mのapplicationDidFinishLaunchingメソッドのラストに
を加えて実行。
だらだらと結果の一覧が表示されるぞっと。
これで、次に保守用メソッドを呼んで、もう一度[db dumpResults]ってやれば、どの部分が削られたかはっきりするわけですわ。
保守用メソッドとしては
とやって、?に保持しておきたい記録件数を指定してやれば、最新の日付から指定した記録件数分さかのぼったあとに、最初に見つかった日付が1件返されるから、これを使って、
の?に指定してやれば、記録件数を越えた部分は削除されるようになるわけです。
とりあえず、最初に正しく最新の日付から保持しておきたい記録件数分さかのぼった日付が検索できてるかどうか確認するメソッド
- (double)getFromLast:(int)inCount
使うSQL文は
ね。てのを用意して、[db getFromLast:3]で表示させた結果がこれ。
秒数が変わらないのでdouble型もそのまま表示させてる。きっちり最新から3個さかのぼった次の記録の日付が返ってます。
つーことで、いけそうなので
- (void)maintainResultSize:(double)inDatetime
も一気に作成。使うSQL文は当然
っす。
あと、getFromLastは指定した件数より記録されている件数が少なかった場合、日付が見つからないので、この場合は-1を返す事とします。なのでapplicationDidFinishLaunching側では
として実行。
これで、いつでも最新の記録3件だけが保持される事になるわけですな。
------------
サンプルプロジェクト:db4.zip
最後に残ったのが保守作業。
極端な話、猿のようにゲームやられてそれを全部記録してたら、iPhoneが破裂しちゃうわけですよ。ま、今回程度の記録なら1件につき100バイトくらいとして、1万件記録しても1MBだけどね。
容量制限はつけるのが仁義ってもんよ。
なので、一定サイズ以上にならないように日付の古いものは削除するようにします。
このために使うSQL文が「iPhoneアプリ開発、その(78)」で使った
select datetime from result order by datetime desc
limit どれだけ offset どの位置から;
と
delete from テーブル名 where どの部分
になるわけですわ。
まずは、ちゃんと保守できているか確認するために、今登録されている結果をすべて表示するメソッドを用意してみるっすよ~。
- (void)dumpResults
使うSQL文自体は単純ですわ。
select datetime, correct, complete from result order by datetime desc
datetimeを大きい順に並べてるのは、最新の日付が上に表示されるようにするため。
めんどくさかったのが、取り出したdouble型のdatetimeをどうやって2009年5月14日 00:50:13といったような表示にするかってところ。
これには、またまたSQLiteBooksのソースのお世話になりました。Book.hで宣言されているcopyrightが日付なんですが、このNSDate*型の変数を画面上ではちゃんと日付で表示してるわけですよ。
さっそく編集>検索>プロジェクト内で検索メニューで出てくる検索ダイアログにcopyrightと打ち込んで検索。DetailViewController.mのtableView:cellForRowAtIndexPath:てメソッドでNSStringに変換してました。
[dateFormatter stringFromDate:book.copyright]
てやつです。
んじゃ、このdateFormatterってなによ?て同一ソース内を検索すると
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeStyle:NSDateFormatterNoStyle];
て感じで準備されてます。NSDateFormatterね。なんでしょ?
困った時は右クリック(iPhoneアプリ開発、その(33)参照)だ。ちなみにオプションキー+クリックという手もある。
出てきたNSDateFormatterの説明を読んでいくと、stringFromDateメソッドが受け取ったNSDateインスタンスの内容を元に、setDateStyleやsetTimeStyleで指定された形式で日付文字列としてNSStringインスタンスを作るメソッドだってのがわかるわけです。
同じように、double型からNSDateインスタンスを作るのはSQLiteBooksのBook.mのhydrateメソッドからNSDateのdateWithTimeIntervalSince1970メソッドを使えばいい(でも、なんでSine1970と思った人はunix 1970でググりましょう)ってのがわかるので、これで必要なクラスとメソッドがそろったことになる。
今回は秒数も表示したいのでsetTimeStyleにはNSDateFormatterNoStyleではなくNSDateFormatterMediumStyleを指定します。他にkCFDateFormatterFullStyleとかkCFDateFormatterShortStyleとかもあるんで、各自ソースを変更していろいろ試してみましょう。とくに日付の方はkCFDateFormatterFullStyleだとiPhone(エミューレター)側の設定>一般>言語環境>書式で選んだ言語によって変化が大きいっす。
あと、printfはNSString*を受け付けないのでC文字列にする必要があるんですが、それにはNSStringのcStringUsingEncodingメソッドを使います。ここらへんはAPIリファレンスをこつこつ調査ね。引数で指定するエンコーディングはNSUTF8StringEncodingでした。こっちは力技。NSShiftJISStringEncodingとかNSJapaneseEUCStringEncodingとか指定して試してみた。まあねえprintfの段階でUTF-16やUTF-32は消えるわけで、今更Shift JISやEUCでもないしね~。
つか、ソースのエンコードをUTF-8にしてるから、日本語普通に使えるんじゃね~か。コンソール。今気づいたわ~。ぬかった~。
実装終わったら、前回のdbAppDelegate.mのapplicationDidFinishLaunchingメソッドのラストに
[db dumpResults];
を加えて実行。
だらだらと結果の一覧が表示されるぞっと。
これで、次に保守用メソッドを呼んで、もう一度[db dumpResults]ってやれば、どの部分が削られたかはっきりするわけですわ。
保守用メソッドとしては
select datetime from result order by datetime desc
limit 1 offset ?
とやって、?に保持しておきたい記録件数を指定してやれば、最新の日付から指定した記録件数分さかのぼったあとに、最初に見つかった日付が1件返されるから、これを使って、
delete from result where datetime <= ?
の?に指定してやれば、記録件数を越えた部分は削除されるようになるわけです。
とりあえず、最初に正しく最新の日付から保持しておきたい記録件数分さかのぼった日付が検索できてるかどうか確認するメソッド
- (double)getFromLast:(int)inCount
使うSQL文は
select datetime from result order by datetime desc
limit 1 offset ?
ね。てのを用意して、[db getFromLast:3]で表示させた結果がこれ。
秒数が変わらないのでdouble型もそのまま表示させてる。きっちり最新から3個さかのぼった次の記録の日付が返ってます。
つーことで、いけそうなので
- (void)maintainResultSize:(double)inDatetime
も一気に作成。使うSQL文は当然
delete from result where datetime <= ?
っす。
あと、getFromLastは指定した件数より記録されている件数が少なかった場合、日付が見つからないので、この場合は-1を返す事とします。なのでapplicationDidFinishLaunching側では
[db dumpResults];
double datetime = [db getFromLast:3];
if (datetime == -1) {
printf("保守ずみ\n");
} else {
[db maintainResultSize:datetime];
[db dumpResults];
}
として実行。
これで、いつでも最新の記録3件だけが保持される事になるわけですな。
------------
サンプルプロジェクト:db4.zip