Objective-Cでタイマーをマスター!10のステップで徹底解説

Objective-CタイマーガイドObjctive-C
この記事は約19分で読めます。

※本記事のコンテンツは、利用目的を問わずご活用いただけます。実務経験10000時間以上のエンジニアが監修しており、常に解説内容のわかりやすさや記事の品質に注力しておりますので、不具合・分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。(理解できない部分などの個別相談も無償で承っております)
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

Objective-Cは、AppleのiOSやmacOSなどのアプリケーション開発に使用されるプログラミング言語の一つです。

このObjective-Cを使って、アプリケーションにタイマー機能を組み込む場合、多くのシチュエーションで役立つことがあります。

例えば、一定の間隔で何らかの処理を行ったり、カウントダウン機能を追加したりと、多岐にわたる応用が考えられます。

タイマーは、プログラムの動作を一時的に停止させることなく、指定した時間が経過した後に特定の処理を実行するためのツールです。

Objective-Cにおけるタイマーの実装は、他のプログラミング言語と比べても独特の部分があるため、その使い方や実装方法をしっかりと理解しておくことが重要です。

また、タイマーの実装においては注意点も存在します。

適切にタイマーを管理しないと、メモリリークなどの問題が発生する可能性もあるため、この記事を通じて、正しい知識と実践方法を身につけることを目指しましょう。

●Objective-Cのタイマーとは

Objective-Cにおけるタイマーは、NSTimerクラスを使用して実装されます。

このNSTimerクラスは、指定した時間間隔で指定したターゲットの指定したメソッドを実行することができる機能を持っています。

NSTimerを使用することで、例えば一定の時間ごとに特定の処理を実行したり、指定した時間後に一度だけ処理を実行するなど、さまざまなタイミングでの処理実行を実現することができます。

また、NSTimerには、一度スタートすると指定した時間間隔で繰り返し実行されるリピーティングタイマーと、指定した時間後に一度だけ実行されるワンショットタイマーの2つの主要なタイプがあります。

しかし、NSTimerを使用する際には、その動作原理や使い方、そして注意点などをしっかりと把握しておくことが求められます。

○タイマーの基本理解

タイマーは、特定の時間が経過した後に特定の処理を行うためのものです。

そのため、何らかの処理を一定の時間後、もしくは一定の時間間隔で実行する場面で頻繁に使用されます。

Objective-CのNSTimerクラスを使用することで、上述のようなタイマーを簡単に作成することができます。

しかし、NSTimerを使用する際には、その特性や動作原理を正しく理解しておくことが必要です。

NSTimerクラスは、Cocoaのイベント駆動型のフレームワークに組み込まれています。

そのため、NSTimerオブジェクトが発火すると、指定されたメソッドが呼び出されるという仕組みになっています。

また、NSTimerを使用する際には、タイマーの動作を制御するためのいくつかのメソッドやプロパティが提供されています。

これにより、タイマーの開始や停止、リセットなどの操作を行うことができます。

●タイマーの作り方

Objective-Cの中でタイマーを使う場合、NSTimerクラスを利用します。

NSTimerクラスは、指定した間隔で特定のメソッドを繰り返し呼び出すためのものです。

このメソッドを「ターゲット」と呼びます。

このクラスを使うことで、一定の時間ごとに特定の処理を行うことができます。

タイマーを作成する際には、次の2つの主要な方法があります。

  1. scheduledTimerWithTimeInterval:メソッドを使った方法
  2. timerWithTimeInterval:メソッドを使った方法

○サンプルコード1:基本的なタイマーの作成

このコードでは、scheduledTimerWithTimeIntervalメソッドを使って、2秒ごとに特定のメソッドを呼び出すタイマーを作成するコードを表しています。

この例では、timeFiredメソッドを2秒ごとに呼び出しています。

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(timeFired) userInfo:nil repeats:YES];

-(void)timeFired {
    NSLog(@"タイマーが発火しました!");
}

このコードを実行すると、2秒ごとに”タイマーが発火しました!”というメッセージがログに出力されます。

○サンプルコード2:一定間隔での処理実行

このコードでは、timerWithTimeIntervalメソッドを使って、3秒ごとに特定のメソッドを呼び出すタイマーを作成するコードを表しています。

この例では、intervalActionメソッドを3秒ごとに呼び出しています。

NSTimer *intervalTimer = [NSTimer timerWithTimeInterval:3.0 target:self selector:@selector(intervalAction) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:intervalTimer forMode:NSDefaultRunLoopMode];

-(void)intervalAction {
    NSLog(@"3秒ごとの処理を実行しています。");
}

このコードを実行すると、3秒ごとに”3秒ごとの処理を実行しています。”というメッセージがログに出力されます。

●タイマーの詳細な使い方

タイマーは、特定の間隔でコードを実行するためのツールとして頻繁に利用されます。

Objective-Cでのタイマーの使い方を理解するために、ここでは2つのサンプルコードを通して詳しく解説していきます。

○サンプルコード3:タイマーの一時停止と再開

このコードでは、NSTimerを使ってタイマーを一時停止、そして再開する方法を表しています。

この例では、特定の条件下でタイマーを停止し、再度開始する方法を表しています。

NSTimer *timer;
BOOL isTimerPaused = NO;

- (void)startTimer {
    if (!timer) {
        timer = [NSTimer scheduledTimerWithTimeInterval:1.0
                                                 target:self
                                               selector:@selector(updateTimer)
                                               userInfo:nil
                                                repeats:YES];
    }
}

- (void)pauseTimer {
    if (!isTimerPaused) {
        [timer invalidate];
        timer = nil;
        isTimerPaused = YES;
    }
}

- (void)resumeTimer {
    if (isTimerPaused) {
        [self startTimer];
        isTimerPaused = NO;
    }
}

- (void)updateTimer {
    NSLog(@"タイマー更新");
}

このコードでは、タイマーを開始するstartTimerメソッド、タイマーを一時停止するpauseTimerメソッド、タイマーを再開するresumeTimerメソッドが定義されています。

一時停止する際には、invalidateメソッドを使ってタイマーを無効化し、timerオブジェクトをnilに設定します。

再開する際には、再度startTimerメソッドを呼び出してタイマーをスタートします。

タイマーが動作中か停止中かを判定するために、isTimerPausedというBOOL変数を利用しています。

このコードを実行すると、”タイマー更新”というメッセージが毎秒ログに出力されます。

一時停止メソッドを実行すると、このログ出力が停止し、再開メソッドを実行すると再びログが出力されるようになります。

○サンプルコード4:タイマーのリセット方法

このコードでは、NSTimerを使ってタイマーをリセットする方法を表しています。

この例では、特定の条件が満たされた際にタイマーを完全にリセットする方法を解説します。

NSTimer *timer;
NSInteger counter = 0;

- (void)startTimer {
    if (!timer) {
        timer = [NSTimer scheduledTimerWithTimeInterval:1.0
                                                 target:self
                                               selector:@selector(updateTimer)
                                               userInfo:nil
                                                repeats:YES];
    }
}

- (void)resetTimer {
    [timer invalidate];
    timer = nil;
    counter = 0;
}

- (void)updateTimer {
    counter++;
    NSLog(@"経過秒数: %ld", (long)counter);
}

このコードでは、タイマーが開始されると毎秒カウンタが1増加し、その経過秒数がログに出力されます。

リセットメソッドresetTimerを呼び出すと、タイマーは無効化され、カウンタが0にリセットされます。

このコードを実行すると、毎秒”経過秒数: 〇”という形でログが出力され、リセットメソッドを呼び出すとカウンタが0にリセットされることが確認できます。

●応用例とサンプルコード

Objective-Cにおけるタイマーは多岐にわたる用途で使用されます。

その一例としてカウントダウン機能、アニメーション制御、スライドショーの実装などがあります。

これらの応用例をサンプルコードを交えて詳しく説明していきます。

○サンプルコード5:タイマーを使ったカウントダウン機能

このコードではNSTimerクラスを使って、カウントダウン機能を実装するコードを表しています。

この例では10秒から1秒ずつ減少させて、0秒になった際に終了メッセージを表示しています。

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    @autoreleasepool {
        __block int count = 10;
        NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
            if (count > 0) {
                NSLog(@"%d", count);
                count--;
            } else {
                NSLog(@"カウントダウン終了");
                [timer invalidate];
            }
        }];
        [[NSRunLoop currentRunLoop] run];
    }
    return 0;
}

上記のコードは10からカウントダウンを開始し、カウントが0になった時点で”カウントダウン終了”というメッセージを表示します。

さらに、タイマーを無効化することで、これ以上の繰り返しを防ぎます。

コードを実行すると、コンソールに10, 9, 8…という形で数字が表示され、最後にカウントダウン終了と表示されます。

○サンプルコード6:タイマーでのアニメーション制御

このコードではNSTimerクラスを使って、アニメーションの制御を行なっています。

この例では、一定間隔で画像を切り替えることでアニメーションを実現しています。

// 仮の画像クラスとメソッドを定義
@interface Image : NSObject
- (void)setImage:(NSString *)imageName;
@end

int main (int argc, const char * argv[]) {
    @autoreleasepool {
        __block int imageIndex = 0;
        NSArray *imageNames = @[@"image1", @"image2", @"image3"];
        Image *image = [[Image alloc] init];

        NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.5 repeats:YES block:^(NSTimer * _Nonnull timer) {
            [image setImage:imageNames[imageIndex]];
            imageIndex = (imageIndex + 1) % [imageNames count];
        }];

        [[NSRunLoop currentRunLoop] run];
    }
    return 0;
}

上記のコードを実行すると、0.5秒ごとに”image1″, “image2”, “image3″という名前の画像が順番に表示されます。

このようにしてアニメーションのような効果を実現することができます。

○サンプルコード7:タイマーを使ったスライドショーの実装

このコードではNSTimerクラスを使って、スライドショーを実現するコードを表しています。

この例では、指定された間隔で画像を順番に表示することでスライドショーを作成しています。

// 仮の画像クラスとメソッドを定義
@interface SlideShow : NSObject
- (void)showImage:(NSString *)imageName;
@end

int main (int argc, const char * argv[]) {
    @autoreleasepool {
        __block int slideIndex = 0;
        NSArray *slideImages = @[@"slide1", @"slide2", @"slide3", @"slide4"];
        SlideShow *slideShow = [[SlideShow alloc] init];

        NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:3.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
            [slideShow showImage:slideImages[slideIndex]];
            slideIndex = (slideIndex + 1) % [slideImages count];
        }];

        [[NSRunLoop currentRunLoop] run];
    }
    return 0;
}

上記のコードを実行すると、3秒ごとに”slide1″, “slide2”, “slide3”, “slide4″という名前の画像が順番に表示され、スライドショーとして画像を楽しむことができます。

●注意点と対処法

Objective-Cでのタイマー使用時、開発者は数々の問題に直面することがあります。特に注意が必要なのが、メモリリークの問題です。

タイマーは、プログラム中で頻繁に使用されることが多いため、メモリリークのリスクが高まります。

ここでは、タイマー使用時のメモリリークについての注意点とその対処法を説明します。

○タイマーのメモリリークについて

Objective-Cでタイマーを使用するとき、往々にしてメモリリークの問題が発生します。

メモリリークは、オブジェクトが不要になったにも関わらずメモリから解放されず、そのメモリ領域が永久に占有されてしまう現象を指します。

タイマーが正しく解放されないと、アプリケーションのパフォーマンス低下やクラッシュの原因となります。

そのため、正しくタイマーを管理し、不要になった際には適切に解放することが重要です。

□サンプルコード8:メモリリークの防止方法

下記のサンプルコードでは、NSTimerを使用してタイマーを作成し、その後適切に解放しています。

// タイマーの作成
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateMethod) userInfo:nil repeats:YES];

// タイマーの破棄
[timer invalidate];
timer = nil;

このコードではNSTimerのscheduledTimerWithTimeIntervalメソッドを使って、1秒間隔でupdateMethodを呼び出すタイマーを作成しています。

この例ではタイマーを適切に解放するために、invalidateメソッドを使用してタイマーを停止させ、その後nilを代入してオブジェクトを解放しています。

この手法によって、タイマーが不要になったときにメモリリークを防ぐことができます。

ただし、タイマーを破棄する前に必ずinvalidateメソッドを呼び出すことが重要です。

invalidateメソッドを呼び出さないと、タイマーは実行中のままとなり、メモリリークの原因となります。

実際に上記のコードを実行すると、1秒ごとにupdateMethodが呼び出されます。

しかし、タイマーを破棄する部分を実行すると、updateMethodの呼び出しは停止し、タイマー関連のメモリが正しく解放されます。

●カスタマイズ方法

Objective-Cを用いたタイマーのカスタマイズについて、独自の要求に応じてタイマーの動作を変更する方法を理解しておくことは、より高度なプログラミングスキルの獲得につながります。

ここでは、カスタムタイマーの作成方法から、複数のタイマーを同時に制御する方法までを説明します。

○サンプルコード9:カスタムタイマーの作成

Objective-Cにおいて、NSTimerクラスを使ってタイマーをカスタマイズする方法を見ていきましょう。

カスタムタイマーを作成することで、特定の条件下でのみ動作するようなタイマーを実装できます。

#import <Foundation/Foundation.h>

@interface CustomTimer : NSObject {
    NSTimer *timer;
}

- (void)startTimer;
- (void)stopTimer;
@end

@implementation CustomTimer

- (void)startTimer {
    if (timer == nil) {
        timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
    }
}

- (void)stopTimer {
    [timer invalidate];
    timer = nil;
}

- (void)timerAction {
    // カスタムアクションをここに記述
    NSLog(@"カスタムタイマー動作中!");
}

@end

このコードでは、NSTimerを使用してカスタムタイマーを作成しています。

この例では、1秒ごとに「カスタムタイマー動作中!」というメッセージをログに出力するタイマーを実装しています。

startTimerメソッドでタイマーを開始し、stopTimerメソッドでタイマーを停止できます。

このコードを実行すると、タイマーが開始され、1秒ごとに指定したアクションが実行されます。

ログには「カスタムタイマー動作中!」というメッセージが繰り返し表示されることが期待されます。

○サンプルコード10:複数のタイマーを同時に制御

複数のタイマーを同時に制御する場面もあります。

たとえば、異なる間隔で動作する複数のタイマーを管理したい場合などです。

ここでは、2つの異なるタイマーを同時に制御する方法を表すコードを紹介します。

#import <Foundation/Foundation.h>

@interface MultiTimerController : NSObject {
    NSTimer *timer1;
    NSTimer *timer2;
}

- (void)startTimers;
- (void)stopTimers;
@end

@implementation MultiTimerController

- (void)startTimers {
    if (timer1 == nil) {
        timer1 = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timer1Action) userInfo:nil repeats:YES];
    }
    if (timer2 == nil) {
        timer2 = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(timer2Action) userInfo:nil repeats:YES];
    }
}

- (void)stopTimers {
    [timer1 invalidate];
    timer1 = nil;
    [timer2 invalidate];
    timer2 = nil;
}

- (void)timer1Action {
    NSLog(@"タイマー1動作中!");
}

- (void)timer2Action {
    NSLog(@"タイマー2動作中!");
}

@end

このコードでは、2つの異なるタイマーを制御しています。

timer1は1秒ごと、timer2は2秒ごとに動作します。

startTimersメソッドで両方のタイマーを開始し、stopTimersメソッドで両方のタイマーを停止できます。

このコードを実行すると、timer1は1秒ごとに「タイマー1動作中!」と、timer2は2秒ごとに「タイマー2動作中!」というメッセージがログに出力されることが期待されます。

まとめ

Objective-Cにおけるタイマーの操作は、アプリケーションの多様な機能を実装する際の基本的なスキルとなります。

基本的なタイマーの作成から、複数のタイマーを同時に制御する方法、さらにはカスタマイズといった高度な操作まで、さまざまなサンプルコードを通じて理解を深めることができたかと思います。

これらの知識を活用し、アプリケーションの品質を向上させ、ユーザーエクスペリエンスを豊かにすることを目指しましょう。

今回学んだ内容を定期的に見返すことで、スキルの定着を図ることができます。