寺子屋管理者

  • アバター画像

教えて!iPhoneアプリ開発全般

公開寺子屋 1 年と 1 か月前に活動

iPhoneアプリ開発全般についての寺子屋です。

NSTimerで設定の時間内の動作をコントロールする方法? (10件の投稿)

← 寺子屋講義   寺子屋講義案内
  • アバター画像 catiapple による3 年と 7 か月前の発言:

    ある時間が来たら、花火が自動で打ち上げられる様にしたいのですが、
    何発か打ち上げるのに、
    打ち上げられるタイミングと言うか、一発一発の間隔を自由に扱う方法はあるのでしょうか?
    一発一発の間隔のリズムを一秒毎とかでは無く、例えば
    1秒、0.5秒、0.5秒、0.8秒、1秒 の様にリズムを変えたいのです。

    上手く質問内容が伝わっていれば良いのですが、
    どなたか、ご教授おねがいいたします。

  • アバター画像 reborn による3 年と 7 か月前の発言:
    t1 = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self …
    t2 = [NSTimer scheduledTimerWithTimeInterval:1.0+0.5 target:self …
    t3 = [NSTimer scheduledTimerWithTimeInterval:1.0+0.5+0.5 target:self …
    

    って感じで複数のNSTimerをスケジュールしてはどうですか?

    あとは実行途中でキャンセルする時の事を考えて、呼び出されたメソッドではインスタンス変数にnilを入れるようにしておけば、未実行のNSTimerの判別もできるでしょう。
     キャンセルする時にはinvalidate送らないとメモリーリークする可能性もあるから気をつけて。

    - (void)timerFireMethod:(NSTimer *)timer
    {
       if (t1 == timer) {
           t1での花火打ち上げ
           t1 = nil;
       }
    }
    

    最初NSTimerは1つだけつくり-timerFireMethod:内で、自分が何番目のタイマーか確認しつつ、新しくNSTimerを1つ作るというの有りだと思います。

    - (void)timerFireMethod:(NSTimer *)timer
    {
     ・・・
     count++;  ←何番目のタイマー起動かをカウントする
     ・・・
     [NSTimer scheduledTimerWithTimeInterval:count番目の待ち時間 target:self …
    }
    
  • アバター画像 catiapple による3 年と 7 か月前の発言:

    reborn先生

    いつもありがとうございます。

    何となく,要領が分かりました。
    トライしてみます。
    また,詰まったら,宜しくお願い致します。

  • アバター画像 catiapple による3 年と 7 か月前の発言:

    reborn先生

    reborn先生のブログで花火打ち上げの章を参考に
    画面をタッチしての発射に加えて
    時間を使い、毎時丁度になったら花火が打ち上がる様にしてみようと
    トライしています。

    教えて頂いた
    複数のNSTimerをスケジュールを使って複数個の花火を打ち上げるのに
    時間を取得して
    if (minute == 00 && second == 00) {
    NSLog(@”時刻はちょうどになりました。”);
    [self fire]; //時間ちょうどになったら、発動されるメソッド。
    }else{
    NSLog(@”時刻はちょうどではありません。”);

    }

    - (void) fire //timeを使って花火をうつタイミングを作る
    {
    self.t1 = [NSTimer scheduledTimerWithTimeInterval:0.5
    target:self
    selector:@selector(timerFireMethod:)
    userInfo:nil
    repeats:NO];
    self.t2 = [NSTimer scheduledTimerWithTimeInterval:0.5 + 1.0
    target:self
    selector:@selector(timerFireMethod:)
    userInfo:nil
    repeats:NO];
    同じ様にt3,t4,t5,t6とつくる。
    }
    上記の様にしてみました。
    そして、
    - (void)timerFireMethod:(NSTimer *)timer
    {
    if (_t1 == timer) {
    //t1での花火打ち上げ

    _t1 = nil;

    }
    }

    ここの”t1での花火打ち上げ” の部分ですが
    画面をタップしての打ち上げの場合はFireworkLayerViewクラスに
    /**
    * 時間が毎時丁度になったら1発、花火を打ち上げる。
    */
    - (void) fireWork
    {
    CGPoint pos = CGPointMake(380, 100);
    starLayer* star = [starLayer layer];
    [star setpos:pos];
    [self.layer addSublayer:star];
    // 直に呼ぶとアニメーションがかからないのでこのようにする。ただし間をあける必要は無いので afterDelay:0 とする
    [star performSelector:@selector(launch) withObject:nil afterDelay:0];
    }
    として、

    ViewContrllor.mに
    - (void)timerFireMethod:(NSTimer *)timer
    {
    if (_t1 == timer) {
    //t1での花火打ち上げ
    FireworkLayerView *timeFire = [[FireworkLayerView alloc]init];
    [timeFire fireWork];

    NSLog(@”t1は打ち上げられました”);
    _t1 = nil;
    //呼び出されたメソッドではインスタンス変数にnilを入れるようにしておけば、未実行のNSTimerの判別もできるでしょう。
    }
    としましたが、発射されません。
    ”t1は打ち上げられました”とログに出るのですが、
    t1での花火の打ち上げの書き方をご教授ください。
    どうも、根本的なところが分っていないようで。。。

    よろしくお願いします。
    gitHubを使ってみました。
    https://github.com/iapple8037/Clock-Firework/tree/master/Clock%20Firework

  • アバター画像 reborn による3 年と 7 か月前の発言:

     おお〜、ちゃんとGitHubから取り出せましたよ〜。

     -timerFireMethod:内で新しく作ったFireworkLayerViewに対してfireWorkメッセージを送っていますが、このFireworkLayerViewが画面にaddViewされていないので、そのまますぐに破棄されているのが原因です。
     -viewDidLoadでaddViewしたFireworkLayerViewに対してfireWorkメッセージを送るのがいいでしょう。

     GitHubに私のブランチをプッシュしようと思うのでSettings(図には私のリポジトリではないのでSettingsは出ていないけど、ここらへんです)のcollaboratorsに
    Takahiro-Kunii
    を登録してください。

  • アバター画像 catiapple による3 年と 7 か月前の発言:

    有り難うございます。 reborn先生

    とりあえず,GitHubのcollaboratorsに登録しました。
    宜しくお願い致します。

  • アバター画像 reborn による3 年と 7 か月前の発言:

     プルして、プルリクエストも送ってみました。
     Xcodeでプルすると、Xcode上でもブランチを切り替えられるようになります。
     ブランチに切り替えて変更部分を参考にするのでもいいですし、マスターにブランチをマージするのもいいでしょう。用が済んだらブランチは破棄してもらってかまいません。
     ↓ Xcodeでのブランチへの切り替えがわからない時は以下の後半を参考にしてください。

    http://ameblo.jp/xcc/entry-11715009956.html

     NSTimerをキャンセルする例として、画面が切り替わって見えなくなるタイミングを使う例を示しておきます。モーダルやタブバーでの別のViewControllerの画面に切り替えられた時に、見えない状態で花火を打ち上げても仕方ないという場合、このようにして未実行のNSTimerを止めます。
     FireworkLayerView.m側の打ち上げ位置調整は、そのままだとiPhoneで画面外になるので、iPad、iPhone両方での対応策の例です。

  • アバター画像 catiapple による3 年と 7 か月前の発言:

    reborn先生

    __weak NSTimer* _timers[6];や NSTimeInterval timeIntervals[]の書き方や

    - (void)viewDidDisappear:(BOOL)animated
    {
    [super viewDidDisappear:animated];

    //残りのタイマーを解除
    for (int i = 0; i < 6; i++) {
    [_timers invalidate];
    _timers = nil;
    }
    }

    等,勉強しつつ
    コードを書き直して,何とか無事動かす事が出来ました。

    @interface ViewController ()内のFireworkLayerView* _fireworkLayerView;
    - (void)viewDidLoad内での _fireworkLayerView = v;等理解で来た気がします。
    大変有り難うございました。

    今回はFireworkLayerViewに時間による発射のメッセージを送るのに_fireworkLayerViewを使いましたが,
    また別の動作を付け足して行く場合,同じようにFireworkLayerView* _fireworkLayerView2;などとして
    FireworkLayerViewにメッセージを送れば良いという事でしょうか?

  • アバター画像 reborn による3 年と 7 か月前の発言:

    _fireworkLayerViewをそのまま使えばいいです。

     _fireworkLayerView = v

    はFireworkLayerViewインスタンスを複製しているわけではありませんよ。
    作成したインスタンス に対し、vという名前は-viewDidLoad内でしか使えないので、どのメソッドでも使えるよう_fireworkLayerViewという名前も同時に付けただけです。

  • アバター画像 catiapple による3 年と 7 か月前の発言:

    reborn先生 有り難うございました。
    説明頂いてから、じっくりそのへんを勉強してみました。

    大変分かりやすく説明頂いたので,なんとなく絡まっていた物が解けてきている感じです。

    今後もよろしくお願いいたします。