43

将来的には、それぞれに関数を記述せずに、3つの小さなイベントをスケジュールできるようにしたいと考えています。どうすればこれを使用できNSTimerますか?ブロックは無名関数を容易にすることを理解していますが、ブロック内で使用できますNSTimerか?もしそうなら、どのように使用できますか?

[NSTimer scheduledTimerWithTimeInterval:gameInterval  
         target:self selector:@selector(/* I simply want to update a label here */) 
         userInfo:nil repeats:NO];
4

9 に答える 9

57

You can make use of dispatch_after if you want to achieve something similar to NSTimer and block execution.

Here is the sample code for the same:

    int64_t delayInSeconds = gameInterval; // Your Game Interval as mentioned above by you

    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);

    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){

        // Update your label here. 

    });

Hope this helps.

于 2013-02-17T19:11:38.157 に答える
29

あなたは実際に呼び出すことができます:

NSTimer.scheduledTimerWithTimeInterval(ti: NSTimeInterval,
                    target: AnyObject, 
                    selector: #Selector, 
                    userInfo: AnyObject?, 
                    repeats: Bool)

次のように使用します。

NSTimer.scheduledTimerWithTimeInterval(1, 
                    target: NSBlockOperation(block: {...}), 
                    selector: #selector(NSOperation.main), 
                    userInfo: nil, 
                    repeats: true)

于 2016-05-05T21:08:43.710 に答える
17

ブロックベースのタイマーAPIはCocoaに存在します(iOS 10+ / macOS 10.12 +以降)–Swift3以降で使用する方法は次のとおりです。

Timer(timeInterval: gameInterval, repeats: false) { _ in
    print("herp derp")
}

…またはObjective-Cの場合:

[NSTimer scheduledTimerWithTimeInterval:gameInterval repeats:NO block:^(NSTimer *timer) {
    NSLog(@"herp derp");
}];

コメントに記載されているように、保持サイクルを回避するために、ブロック内で強力な自己参照を使用しないように注意してください(詳細については)。

iOS10、macOS 12、tvOS 10、watchOS 3より古いバージョンのOSをターゲットにする必要がある場合は、他のソリューションのいずれかを使用する必要があります。

于 2016-10-25T15:09:12.263 に答える
9

@Peter Pengの回答のObjective-Cバージョン:

_actionDelayTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:[NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"Well this is useless.");
}] selector:@selector(main) userInfo:nil repeats:YES];
于 2016-08-10T21:55:35.313 に答える
6

It's pretty easy, but it isn't included in Apple framework, not yet at least.

You can write a block-based wrapper for NSTimer yourself, e.g. using GCD, or you can use existing 3rd-party libraries like this one: https://github.com/jivadevoe/NSTimer-Blocks.

于 2013-02-17T19:12:52.673 に答える
3

NSTimer witchにカテゴリを作成しました。これにより、ブロックで使用できるようになります。

https://github.com/mBrissman/NSTimer-Block

于 2014-12-05T23:47:35.897 に答える
2

2018年後半の時点で、次のように正確に実行します。

Timer.scheduledTimer(withTimeInterval: 0.25, repeats: true) { timer in
  print("no, seriously, this works on iPhone")
} 

@JohnnyCに感謝します!

本当に奇妙です!

ここに画像の説明を入力してください

于 2018-12-21T20:53:40.260 に答える
0

私はこのハックが大好きです@Peter-Pang!! BlockOperationはオンザフライで作成され、実行中のキューが所有するタイマーが所有し、ブロックのメインセレクターを呼び出して実行します。

のために更新Swift 3

Timer.scheduledTimer(timeInterval: 1, target: BlockOperation { // ... }, selector: #selector(Operation.main), userInfo: nil, repeats: false)

于 2017-03-14T15:16:34.917 に答える
0

これを実行し、dealloc、arc、retaincyclesなどを自動処理するマクロを作成しました。弱参照の使用について心配する必要はありません。また、常にメインスレッドになります

#define inlineTimer(__interval, __block) {\
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((0.0) * NSEC_PER_SEC)), dispatch_get_main_queue(), (__block));\
[NSTimer scheduledTimerWithTimeInterval:__interval repeats:YES block:^(NSTimer *__timer) {\
if (self.window != nil) {\
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((0.0) * NSEC_PER_SEC)), dispatch_get_main_queue(), (__block));\
} else {\
[__timer invalidate];\
}\
}];\
}

使用例:

__block ticks = 0;

inlineTimer(0.5, ^{
    ticks++;
    self.label.text = [NSString stringWithFormat:@"Ticks: %i", ticks];//strong reference to self and self.label won't cause retain cycle! Wahoo
});

self.labelは弱参照ではありませんが、マクロの構造により、これはすべて自動的に解放されることに注意してください。

当然、これはUIクラスでのみ機能します。これは、.windowがいつdeallocする必要があるかをチェックしているためです。

于 2020-08-11T06:15:59.123 に答える