アイコンと起動中の画面、スタート画面を作る:iPhoneアプリでアナログ時計を作る

前回、iPhoneアプリのアナログ時計の背景が、時間で変わるようにしました。本当は、次に時計の針をグルグル回せるようにするつもりだったのですが、

全然上手くいかないまま時間ばかりが経ってしまうので、一旦諦めました。

とりあえず、自分のモチベーションが下がる前に、アプリとして形にするのを優先することにしました。
ダメな男です。でも、人間ですから。ハイ。


まずは、アイコンと起動中の画面です。これは、「よくわかるiPhoneアプリの教科書」でやったことがあるので、何の問題も無くできました。
XcodeのprojectのSummaryへ画像をドラッグアンドドロップするだけです。


次に、スタート画面です。
これは、「15歳からはじめる iPhone わくわくゲームプログラミング教室」でゲームにスタート画面を付ける際に学習しました。
New Fileして、新たにstartViewControllerというクラスを作ります。
appDelegate.mで、最初に起動するクラスを、今まで作って来たviewControllerからstartViewControllerへ移します。

#import "acAppDelegate.h"
#import "acViewController.h"
#import "startViewController.h"

@implementation acAppDelegate

@synthesize window = _window;
@synthesize viewController = _viewController;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    startViewController *startController = [[startViewController alloc] initWithNibName:@"startViewController" bundle:nil];
    
    self.window.rootViewController = startController;
    
    [self.window makeKeyAndVisible];
    return YES;
}

次に、startViewController.mでスタート画面と時計画面へ行けるボタンを設置します。

#import "startViewController.h"
#import "acViewController.h"
#import 

@implementation startViewController

- (void)viewWillAppear:(BOOL)animated{
    self.view.layer.contents =(id)[UIImage imageNamed:@"start_w640.png"].CGImage;
    
    UIButton *button =[UIButton buttonWithType:UIButtonTypeCustom];
    button.frame =CGRectMake(64, 340, 200, 46);
    [button setImage:[UIImage imageNamed:@"button_startClock.png"] forState:UIControlStateNormal];
    [button addTarget:self action:@selector(showClockView) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
}

- (void)showClockView {
    acViewController *clockController =[[acViewController alloc] initWithNibName:@"acViewController" bundle:nil];
    
    clockController.modalTransitionStyle =UIModalTransitionStyleFlipHorizontal;
    [self presentModalViewController:clockController animated:YES];
}


最後に、viewControllerにスタート画面(めにゅー)へ戻れるボタンを設置しました。

@implementation acViewController


- (void)viewWillAppear:(BOOL)animated{
    
    baseLayer =[self.view layer];

    [self setBackLayer];
    [self setTime];
    
    /////時計モードの表示初期化/////
    //文字盤
    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];
    
    
    //分針
    layer_min_hand =[CALayer layer];
    layer_min_hand.bounds =CGRectMake(0, 0, 16, 140);
    layer_min_hand.anchorPoint =CGPointMake(0.5, 0.93);
    layer_min_hand.position =CGPointMake(160, 180);
    layer_min_hand.contents =(id)[UIImage imageNamed:@"min_hand.png"].CGImage;
    layer_min_hand.zPosition =30;
    [baseLayer addSublayer:layer_min_hand];
    
    //時針
    layer_hour_hand =[CALayer layer];
    layer_hour_hand.bounds =CGRectMake(0, 0, 16, 100);
    layer_hour_hand.anchorPoint =CGPointMake(0.5, 0.92);
    layer_hour_hand.position =CGPointMake(160, 180);
    layer_hour_hand.contents =(id)[UIImage imageNamed:@"hour_hand.png"].CGImage;
    layer_hour_hand.zPosition =40;
    [baseLayer addSublayer:layer_hour_hand];
    
    //秒針
    layer_sec_hand =[CALayer layer];
    layer_sec_hand.bounds =CGRectMake(0, 0, 20, 150);
    layer_sec_hand.anchorPoint =CGPointMake(0.5, 0.93);
    layer_sec_hand.position =CGPointMake(160, 180);
    layer_sec_hand.contents =(id)[UIImage imageNamed:@"sec_hand.png"].CGImage;
    layer_sec_hand.zPosition =50;
    [baseLayer addSublayer:layer_sec_hand];
    
    //針の中心
    CALayer *layer_center;
    layer_center =[CALayer layer];
    layer_center.bounds =CGRectMake(0, 0, 20, 20);
    layer_center.position =CGPointMake(160, 180);
    layer_center.contents =(id)[UIImage imageNamed:@"center.png"].CGImage;
    layer_center.zPosition =60;
    [baseLayer addSublayer:layer_center];
    
    //メニューへのボタン
    UIButton *button =[UIButton buttonWithType:UIButtonTypeCustom];
    button.frame =CGRectMake(10, 390, 100, 46);
    [button setImage:[UIImage imageNamed:@"button_toMenu.png"] forState:UIControlStateNormal];
    [button addTarget:self action:@selector(backToMenu) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
    
    [self setClock];
    [self startClock];//タイマー始動
}

- (void)viewDidLoad
{
    [self setBackLayer];//画面初期化で背景決め(画面戻ってきた時の対策)
}

- (void) onTimer:(CFRunLoopTimerRef *)timer {
    if (isClockMode) {
        [self setTime];
        [self setClock];
        if (pre_h != now_h) {
            [self setBackLayer];
            pre_h =now_h;
        }
        //NSLog(@"onTimer");
    }
}

- (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);
    layer_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);
    layer_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);
    layer_hour_hand.transform = transform_h;
    //NSLog(@"%d", now_h);
}

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

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

- (void)backToMenu {
    [self dismissModalViewControllerAnimated:YES];
}

@end

背景の切り替わりタイミング判定をsetBackLayerメソッドに書いておくと、画面を切り替えて戻って来た時に、背景が表示されませんでした。
setBackLayerメソッドでは、純粋に背景切り替え処理のみにして、切り替わりのタイミング判定は、タイマーの方でやることにしました。
また、画面の切り替わり時に、viewDidLoadメソッドでsetBackLayerメソッドを呼び出すようにもしておきました。

やっつけで画像を作ってしまったので、リリースまでにはデザインをし直すつもりです。
あとは、頓挫している分針の自由回転をFIXさせて、簡単なクイズモードを付けて完成にします(結局、クイズモードを付ける余力もありませんでした)。
次は、AppStoreへ申請に出すところを記事に書けたらと思います。

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