頭と尻尾はくれてやる!

パソコンおやじのiPhoneアプリ・サイト作成・運営日記


NSDateから日付を取る時に失敗した

iOSアプリのアップデートを申請、リリースされたんだけど、今回修正したバグのお話だよ。

先週の月曜日に「赤ちゃんの成長グラフ(Lite)」アプリのアップデートの申請をしたんだけど、無事土曜、日曜にリリースされたんだ。

育児パパ! サイトのデータをiPhoneアプリへ送る方法
↑内容はこんな感じなんだけど、ここでは謙虚にバグ修正の話を書いておくよ。徳川家康も三方ヶ原で武田信玄の軍にボコボコにされて凹んでるところの自画像を描かせたって言うし、、、うん、ちょっと話が飛びすぎたね。

そもそも今回のバグはブラジルのママさんから問い合わせが来たので気が付いたんだ。メールのアカウントからブラジル、名前をGoogleの画像検索で問い合わせると女性らしいのでブラジルのママさんと推測してるだけでホントはどうかは不明だけどね。でもやっぱりブラジル人女性ってだけでムチムチでサンバ踊ってるイメージしちゃってなんだかバグ対策頑張っちゃったよ。実はだいぶ前から同じ内容のクレームが某国のレビュー欄に記載されていたんだけど、何かの勘違いじゃないの?とスルーしてたんだ。酷い開発者だね。

ムチムチママさんにサンバのリズムで苦情を言われたらやっぱり対策しないと日本男児の名が廃るってことで重い腰を上げたわけだけど、内容がNSDateあたりの問題なのでホントにそんなバグがあるのか?ここ日本の開発環境で再現するのか?って疑問に思いつつコードをチェックしていたんだけどさ、やっぱりよくわからないんだ。国内のユーザーから同様の苦情が来たことなんてないし。iPhoneの設定に起因するモノで俺の開発環境じゃ再現しないのかなあと思いかけたんだけど、設定アプリの時刻をブラジルに設定してみたら、簡単に再現したんだよ!何度やっても再現するんだ。

もっともバグも再現するのは対処しやすいよね。ありがたいことだよ。
車がおかしいからディーラーに持って行ったのにいざ見てもらう時にはおかしい挙動がないことってホント悔しいもんね。ちくしょう!

ともかく不具合の原因はこんな感じ。
やりたかったのはNSDateオブジェクトから年月日の各数値を取り出したかったんだ。シンプルにしたコードはこんなところ:
//NSDateオブジェクト作成
NSDate *date = [NSDate date];
NSLog(@"date:%@",date);

//年月日を取得する
NSCalendar *calendar = [NSCalendar currentCalendar];
NSUInteger flags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
NSDateComponents *cmp = [calendar components:flags fromDate:date];
NSLog(@"%d / %d / %d",cmp.year,cmp.month,cmp.day);
これを普通に動かすと
date:2012-05-31 00:44:09 +0000
2012 / 5 / 31
って感じで出力されるんだ。実際に実行したのは真夜中じゃなくて31日の朝9:44分頃だよ。

次にiPhone実機の設定アプリにある
一般>日付と時刻>自動設定
ってところ、デフォルトはオンで東京になっていたんだけど、これを”オフ”にして”時間帯”をブラジルのサンパウロにしてみる。そうそう、この設定はiPhoneシミュレータにはないみたいだから実機でテストしたよ。

iPhoneで日付と時刻を設定

↑設定したところだけど、朝にやったのにステータスバーに表示される時刻は昨日の晩になってるね。今頃サンパウロは夜なんだな。

この状態で先ほどのコードを実行すると、
date:2012-05-31 00:44:50 +0000
2012 / 5 / 30
って出るんだ。NSDateが持つ情報は同じだけど日付がずれてる。現地じゃどうなのってのをNSCalendarが対応してるんだな。
ホントはここでも5/31って出力して欲しかったわけで、こういうのをありがた迷惑、、、じゃなくて開発者の無知って言うんだね。

結局NSCalendarオブジェクトに対して
[calendar setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
としておいたら期待通りに動いてくれたよ。


揚げ物用油の痛み具合を評価するアプリ案

俺は普段からこういうアプリがあったらいいなってのをメモしているんだけど、この前「揚げ物に使ってる油をそろそろ交換した方がいいか評価するアプリ」ってコロッケを揚げた後にメモしたよ。

一般的にはどんなもんだろうなと思って調べてみたらこんなのがあったんだ。
揚げ物油はいつ換えますか? - Yahoo!知恵袋

あれ?みんな結構頻繁に換えてるんだね、、、


スクショ画像が小さいとiTCでアプリの説明文が変更できない

iTunes Connectでアプリの説明文を変更しようとしたんだけどさ、スクリーンショットの画像不備で変更できなかったってお話だよ。

今回のアプリのアップデート版リリースを機にApp Storeで表示される説明文を久しぶりに変更をしようしたんだけど、次のようなメッセージが出てきて文章の変更をさせてくれなかったんだよ。

In order to save your changes, all iPhone/iPod touch screenshots must be a .jpeg, .jpg, .tif, .tiff, or .png file that is 960x640, 960x600, 640x960 or 640x920 pixels, at least 72DPI, and in the RGB color space.

もうどこにも320x480って数字はないんだね、、、

そう言えば前からAppleからそんなメール来てたよ。App Store用のアプリのスクリーンショットのサイズが小さいから大きいのにしろって。
今アップしてるのは320x480ピクセルの画像ファイルなんだ。いや、正確にはステータスバーの分縦20px少ないかな。まあいいや、要はRetinaじゃないiPhoneの画像サイズだよね。
Retinaディスプレイでこの画像をApp Storeで見てもさしてひどいと思わなかったんだ。元々App Storeで表示される画像って少し小さく表示されるからうまくごまかされるんだろうね。
あと、「赤ちゃんの成長グラフ(Lite)」アプリは若気の至りでたくさんローカライズしまくったので各言語でスクリーンショットを揃えるのがえらく面倒なんだよ。しかもフルバージョンとLite版の二つあるし。

まあそんなわけでスクリーンショットの変更はしていなかったんだけど、こうなったらやるしかないよね。


"時計の針を進める"は英語では?

今時計アプリを作っているんだけどさ、その辺りの英語表現のお話だよ。
理想的にはアプリ内にヘルプなんてなくて見ただけで使えるってのが理想だけど、そうそう言ってられなくてやっぱり調べたい人のためにヘルプページも欲しいしね。

"時計の針を進める"というのは英語だとこんな感じなのかな。
"set the clock forward one hour" (8010)
"set the clock ahead one hour" (5890)
"put the clock forward one hour" (3940)
"advance the clock one hour" (3640)
"set the clock one hour forward" (2540)
"put the clock forward by one hour" (344)

カッコ内の数字はGoogle先生に聞いた検索結果の数だよ("付きね)。
手元の辞書には
put a clock forward (by) one hour
なんて感じでbyはあってもなくてもよさそうだけど、Google先生によると無い方が自然なのかな。

ちなみに1時間針を進めるってのはサマータイムうんぬんの文脈で出てきてたね。


それじゃ時計の針を戻すのは英語で何て言うの?と思って調べてみると、、、
"set the clock back one hour" (36900)
"put the clock back one hour" (3510)
いろいろあるんだろうけど、このあたりかな。


構造体を配列に入れる方法

今作っている時計アプリで時計の情報を構造体として持っているんだけどさ、それを配列に入れる方法を調べたってお話だよ。

時計の情報をこんな感じで定義してるんだ。
typedef struct {
    int level;
    int hour;
    int minute;
} ClockInfo;
メソッド呼び出し時に引数として使う時に
ClockInfo clockInfo;
clockInfo.level = level;
clockInfo.hour = hour;
clockInfo.minute = minute;
[clockView drawFor:clockInfo];
ってな感じでまとめられるので便利なんだけど、これを配列に入れたくなったんだよね。
NSMutableArrayなんかの配列には整数そのままだと入れられないとかあるじゃない、あんな感じで一工夫必要みたいなんだよ。

調べてみたら、ずばりそのまま
構造体を NSDictionary や NSArray に格納する方法 - Over&Out その後
なんてのがあったよ、ありがたいね。
記事中はNSDictionaryなんだけど、配列に突っ込む場合はこんな感じ、といっても同じだけどさ。
ClockInfo clockInfo;
clockInfo.level = currentLevel;
clockInfo.hour = currentHour;
clockInfo.minute = currentMinute;
NSValue *value = [NSValue value:&clockInfo withObjCType:@encode(ClockInfo)];
[array addObject:value];
もちろんここではarrayはNSMutableArrayクラスのオブジェクトだよ。

配列から取り出して使う時は下のような形で。
NSValue *value = [array objectAtIndex:i];
ClockInfo clockInfo;
[value getValue:&clockInfo];
しっくりこないけど、これでいけるんだよね。




Copyright ©頭と尻尾はくれてやる!. Powered by FC2 Blog. Template by eriraha.

FC2Ad