2010年7月27日火曜日

Day 1 エラーの原因と正しい処理の内容

updateLabelクラスを、beforeからafterに書き換えたところ、エラーがなくなりシミュレータが動いた。

before
-(void)updateLabel {
 NSDate* now = [NSDate date];
 int hour = 23 - [[now dateWithCalendarFormat:nil timeZone:nil] hourOfDay];
 int min = 59 - [[now dateWithCalendarFormat:nil timeZone:nil] minuteOfHour];
 int sec = 59 - [[now dateWithCalendarFormat:nil timeZone:nil] secondOfMinute];
 countdownLabel.text = [NSString stringWithFormat:@"%02d:%02d:%02d", hour, min,sec];
}

updateLabelクラスでは、ラベルに表示する時刻を生成している。
beforeでエラーが出るのは次の3行。
1: int hour = 23 - [[now dateWithCalendarFormat:nil timeZone:nil] hourOfDay];
2: int min = 59 - [[now dateWithCalendarFormat:nil timeZone:nil] minuteOfHour];
3: int sec = 59 - [[now dateWithCalendarFormat:nil timeZone:nil] secondOfMinute];

after
-(void)updateLabel {
NSDate* now = [NSDate date];
 NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
 NSDateComponents *dateComponents = [gregorian components:(NSHourCalendarUnit  | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate:now];
 NSInteger hour = [dateComponents hour];
 NSInteger minute = [dateComponents minute];
 NSInteger second = [dateComponents second];
 [gregorian release];
 countdownLabel.text = [NSString stringWithFormat:@"%02d:%02d:%02d", hour, minute, second];
}  

正しく動作する、updateLabelクラスの主な処理は以下の通り。
---------------------------
NSDate* now = [NSDate date];
NSDateクラスブジェクトを生成する
dateメソッドで、現在の日時(経過時間)を取得する

NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSCalendarクラスオブジェクトの生成と初期化を行う
initWithCalendarIdentifierメソッドは、NSString型の引数をとる。
引数は、NSLocaleクラスのNSLocale Calendar Keysで定義されている。
NSGregorianCalendarは、グレゴリオ暦を指定している。

NSDateComponents *dateComponents = [gregorian components:(NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate:now];
NSDateComponentsクラスオブジェクトの生成を行う。
NSDateComponentsクラスは、カレンダーの年、月、日、時、分、秒、曜日を保持する。
オブジェクトの取得は、NSCalendarクラスのcomponentsメソッドを使用する。
componentsメソッドの引数は2つ。ひとつめは、Calendar Units。取得したいデータ(今回だと、時、分、秒)のこと。
ふたつめは、現在の日時(取得済み)。

形成されたNSDateComponentsから時、分、秒を取り出す。

Calendar Unitsで取得したいデータが複数ある場合は、論理和で指定する。