背景を時間に合わせて変える:iPhoneアプリでアナログ時計を作る



前回、iPhoneアプリのアナログ時計部分が完成しました。たまたま付けた当サイト「おぼえよ」の背景画が、時間が変わっても昼間のままなのが

何か気持ち悪いので、時間に合わせて背景も変わるようにしてみました。

この仕組み自体は、トップページのFlashで昼と夜の2枚だけですが既にやっているので、特に難しいことはありませんでした。
ただ、Flashのようにタイムラインが無いので、その時に合った背景のフレームをenterFrameで指し続けるというのが出来そうにありません。0.5秒間隔で画像を読み込み続けるのも気持ち悪いので、pre_hという変数に過去の時間を入れ、now_hと比較して、違ってたら画像を変えるか否かを判定するようにしました。
変える画像は、朝・昼・夕方・晩の4種類用意しました。
ソースコードは、以下のようになりました。って、本当はソースコード出すのも恥ずかしいのですが、落ち着いた頃に初心者の頃の自分を自分で笑う楽しみにもなるので、出しちゃいます。w

@implementation acViewController

CALayer *sec_hand;//秒針レイヤー
CALayer *min_hand;//分針レイヤー
CALayer *hour_hand;//時針レイヤー
CALayer *layer_back;//背景レイヤー
CALayer *baseLayer;//ベースレイヤー
NSTimer *timer;

NSDate *now;
NSDateFormatter *formatter;
int now_h;
int now_m;
int now_s;
int pre_h =25;


- (void) onTimer:(CFRunLoopTimerRef *)timer {
    [self setTime];
    [self setClock];
    [self setBackLayer];
}

- (void)setTime {
    now =[NSDate date];
    formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"kk"];
    now_h = [[formatter stringFromDate:now] intValue];
    [formatter setDateFormat:@"mm"];
    now_m = [[formatter stringFromDate:now] intValue];
    [formatter setDateFormat:@"ss"];
    now_s = [[formatter stringFromDate:now] intValue];    
}

- (void)setClock {    
    //秒針の動き
    CATransform3D transform_s = CATransform3DIdentity;
    transform_s = CATransform3DRotate(transform_s, (360 * now_s / 60) * M_PI / 180.0, 0, 0, 1);
    sec_hand.transform = transform_s;
    
    //分針の動き
    CATransform3D transform_m = CATransform3DIdentity;
    transform_m = CATransform3DRotate(transform_m, (360 * now_m / 60 + ((360 / 60) * now_s /60)) * M_PI / 180.0, 0, 0, 1);
    min_hand.transform = transform_m;
    
    //時針の動き
    CATransform3D transform_h = CATransform3DIdentity;
    transform_h = CATransform3DRotate(transform_h, (360 * now_h / 12 + ((360 / 12) * now_m / 60)) *M_PI / 180.0, 0, 0, 1);
    hour_hand.transform = transform_h;
    //NSLog(@"%d", now_h);
}

- (void)setBackLayer {
    //背景を決める
    
    if (pre_h != now_h) {
        if (6 <= now_h && now_h <10 ) {
            layer_back.contents =(id)[UIImage imageNamed:@"oboeyo_back_morning.png"].CGImage;
        } else if (10 <= now_h && now_h < 17 ) {
            layer_back.contents =(id)[UIImage imageNamed:@"oboeyo_back_day.png"].CGImage;
        } else if (17 <= now_h && now_h < 19 ) {
            layer_back.contents =(id)[UIImage imageNamed:@"oboeyo_back_sunset.png"].CGImage;
        } else if (19 <= now_h && now_h < 24) {
            layer_back.contents =(id)[UIImage imageNamed:@"oboeyo_back_night.png"].CGImage;
        } else if (0 <= now_h && now_h < 6) {
            layer_back.contents =(id)[UIImage imageNamed:@"oboeyo_back_night.png"].CGImage;
        }
        pre_h =now_h;
    }    
}

- (void)viewWillAppear:(BOOL)animated{
    
    baseLayer =[self.view layer];
    
    //背景
    layer_back =[CALayer layer];
    layer_back.bounds =CGRectMake(0, 0, 320, 480);
    layer_back.position =CGPointMake(160, 240);
    [self setBackLayer];
    layer_back.zPosition =10;
    [baseLayer addSublayer:layer_back];
    
    [self setTime];
        
    //文字盤
    CALayer *layer_clock_plate =[CALayer layer];
    layer_clock_plate.bounds =CGRectMake(0, 0, 303, 303);
    layer_clock_plate.position =CGPointMake(160, 180);
    layer_clock_plate.contents =(id)[UIImage imageNamed:@"oboeyo_clock_plate2.png"].CGImage;
    layer_clock_plate.zPosition =20;
    [baseLayer addSublayer:layer_clock_plate];
    
    
    //分針
    min_hand =[CALayer layer];
    min_hand.bounds =CGRectMake(0, 0, 16, 120);
    min_hand.anchorPoint =CGPointMake(0.5, 0.93);
    min_hand.position =CGPointMake(160, 180);
    min_hand.contents =(id)[UIImage imageNamed:@"min_hand.png"].CGImage;
    min_hand.zPosition =30;
    [baseLayer addSublayer:min_hand];
    
    //時針
    hour_hand =[CALayer layer];
    hour_hand.bounds =CGRectMake(0, 0, 16, 100);
    hour_hand.anchorPoint =CGPointMake(0.5, 0.92);
    hour_hand.position =CGPointMake(160, 180);
    hour_hand.contents =(id)[UIImage imageNamed:@"hour_hand.png"].CGImage;
    hour_hand.zPosition =40;
    [baseLayer addSublayer:hour_hand];
    
    //秒針
    sec_hand =[CALayer layer];
    sec_hand.bounds =CGRectMake(0, 0, 20, 140);
    sec_hand.anchorPoint =CGPointMake(0.5, 0.93);
    sec_hand.position =CGPointMake(160, 180);
    sec_hand.contents =(id)[UIImage imageNamed:@"sec_hand.png"].CGImage;
    sec_hand.zPosition =50;
    [baseLayer addSublayer:sec_hand];
    
    [self setClock];
    [self startClock];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

- (void) startClock {
    timer = [NSTimer 
             scheduledTimerWithTimeInterval:0.1
             target: self 
             selector:@selector(onTimer:) 
             userInfo:nil 
             repeats:YES];
}

- (void) stopClock {
    [timer invalidate]; // timerをストップ
}

@end

前回に比べて、いろんなものを個別のメソッドとしてviewWillAppearメソッドから追い出したので、いろんな変数も外に出しました。
段々グチャグチャになってきたので、そろそろ「cocos2d for iPhone レッスンノート」のように部品毎にクラスにしたいところです。が、しかし、その作業自体が初めてなので、やりたい気持ちをグッとこらえて、ここはアプリを完成させることを優先することにしました。
ちなみに、背景画像があまりにもヤッツケだったので、少しだけ神経使ってトリミングし直しました。また、文字盤のメモリも消したりできるように別レイヤーにしたりするなど、細かいところを前回から少しだけいじっています。

さて、次は分針を回すことができるように修正したいと思います
思ったよりも分針を回すのが大変で、なかなか正常動作してくれず、1週間ほど頓挫してしまいました。ここでモチベーションが下がるとズルズルいってしまう気がしたので、先にアイコンやらスタート画面を作ることにしました

★★★自作iPhoneアプリをAppStoreでリリースするまでの道のり★★★