21

メインキューにディスパッチしてリピートを作成する理由を誰かが説明できるかどうか疑問に思ってNSTimerいます。使用しているときでもperformselectorOnMainThread、それを起動させるためにRUNLOOPに追加する必要があります。

以下は私の質問の例です:

#define queue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
#define mainqueue dispatch_get_main_queue()

- (void)someMethodBeginCalled
{
    dispatch_async(queue, ^{
        int x = 0;
        dispatch_async(mainqueue, ^(void){
            if([_delegate respondsToSelector:@selector(complete:)])
                [_delegate complete:nil];
        });
    });
}

- (void)compelete:(id)object
{
    [self startTimer];

    //[self performSelectorOnMainThread:@selector(startTimer) withObject:nil waitUntilDone:NO];
}

- (void)startTimer
{
    NSTimer timer = [NSTimer timerWithTimeInterval:3 target:self selector:@selector(callsomethingelse) userInfo:nil repeats:YES];

    //NSDefaultRunLoopMode
    [[NSRunLoop currentRunLoop] addTimer:_busTimer forMode:NSRunLoopCommonModes];
}

編集: 私はこの質問の言い回しが非常に貧弱だと思います。と呼んだらなぜ [[NSRunLoop currentRunLoop] addTimer:_busTimer forMode:NSRunLoopCommonModes];必要なのか知りたいのですが。その行を含めないと、タイマーは起動しません。startTimersomeMethodBeginCalled

たとえば、startTimerから電話をかけると、回線を削除でき、タイマーは60秒ごとに起動します。viewDidLoadNSRunLoop

4

6 に答える 6

22

そしてNSTimer、これがrunloopにを追加する方法です:

NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:timer forMode:NSDefaultRunLoopMode];
于 2013-03-20T15:06:29.617 に答える
19

代わりに、いつでもこの方法を使用できます。

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

これにより、実行ループに自動的に追加されるため、行が節約されます。

于 2012-03-29T02:32:25.503 に答える
4

なぜなら、ドキュメントが言うように:

タイマーは実行ループと連動して機能します。タイマーを効果的に使用するには、実行ループがどのように動作するかを知っておく必要があります。「NSRunLoopおよびスレッドプログラミングガイド」を参照してください。特に、実行ループはタイマーを保持するため、実行ループにタイマーを追加した後でタイマーを解放できることに注意してください。

これは、AppleがNSTimerのコードを書いたときに行った設計上の決定であり(そして、そうする正当な理由があると確信しています)、それを回避するために私たちにできることは何もありません。本当に面倒ですか?

于 2012-03-29T02:03:42.797 に答える
3

@sosbornが言ったように、NSTimersはsに依存しNSRunLoop、GCDキューは実行ループを持たないスレッドを作成するため、 。NSTimerではうまく機能しませんGCD

この問題に関する他のStackOverflowの質問を確認してください:GCDシリアルキューでNSTimersをスケジュールして無効にするのは安全ですか?

その問題を解決するために、私はhttps://github.com/mindsnacks/MSWeakTimerMSWeakTimerを実装しました(そして、最後のWWDCでlibdispatchエンジニアによって実装がチェックされました!)

于 2013-09-07T01:24:33.483 に答える
1

GCDキューは実行ループのないスレッドを作成するため、タイマーメソッドは呼び出されません

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
   [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
       NSLog(@"Timer method from GCD main queue");
   }];

});

ただし、メインキューにディスパッチされると、タイマーメソッドが呼び出され、メインスレッドの実行ループに追加されます。

dispatch_async(dispatch_get_main_queue(), ^{
   [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
       NSLog(@"Timer method from GCD main queue");
   }];

});
于 2017-04-05T03:46:17.970 に答える
0

私の場合、runloopにタイマーを追加しても機能しませんでした。メインスレッドでタイマーを作成する必要がありました。私はMultipeerConnectivityデリゲートでこのスレッドの作成を行っていました。

    dispatch_async(dispatch_get_main_queue(), ^{
        self.timer = [NSTimer scheduledTimerWithTimeInterval:self.interval  invocation: self.invocation repeats:YES];
    });
于 2016-02-14T00:22:17.687 に答える