2011-02-09 10 views
2

私はタイマーを持つアプリケーションを作っています。ある時刻から0までの分と秒を数えます。これが起こると、私はalertviewを起動します。スレッドとNSTimer

私の構造はこれです:

Mainthreadメソッドは、新しいスレッドを割り当て、それを初期化します。 スレッドのエントリポイント(メソッド)には、時間を計算するためのメソッドを呼び出すタイマーがあり、時間が経過すると、アラートビューが表示されます。

しかしこれは正しいですか?メインとは別のスレッドからGUIを更新しているので、それは正しくありませんか?また、このスレッドからalertviewを表示しています。

alertviewを更新して表示するためのすべてのロジックをカプセル化し、nstimerが呼び出すメソッドでperformSelectorInMainThreadを使用する別の方法を考えましたが、これは正しいですか?

お時間をいただきありがとうございます。

+0

時計はどのようになったのですか?私は2秒ごとにURLを監視する必要がある同様の問題があります。私はどのような解決策を使ったのだろうかと思います。 [email protected] – leo

答えて

4

どのくらいの時間が残っているかを判断するのが簡単だと仮定すると、メインスレッドでタイマーを実行するだけです。タイマーは現在のrunloopにアタッチされるため、どこでもブロックされず、コールバックメソッドの実行に過度の時間を費やす必要がないため、UIをうまく更新できます。

- (void) initializeTimerWithEndTime: (NSDate *) endTime 
{ 
    // call this on the main thread & it'll automatically 
    // install the timer on the main runloop for you 
    self.countdownTimer = [NSTimer scheduledTimerWithTimeInterval: 1.0 
                  target: self 
                 selector: @selector(timerTick:) 
                 userInfo: endTime 
                  repeats: YES]; 
#if __TARGET_OS_IPHONE__ 
    // fire while tracking touches 
    [[NSRunLoop mainRunLoop] addTimer: self.countdownTimer 
           forMode: UITrackingRunLoopMode]; 
#else 
    // fire while tracking mouse events 
    [[NSRunLoop mainRunLoop] addTimer: self.countdownTimer 
           forMode: NSEventTrackingRunLoopMode]; 
    // fire while showing application-modal panels/alerts 
    [[NSRunLoop mainRunLoop] addTimer: self.countdownTimer 
           forMode: NSModalPanelRunLoopMode]; 
#endif 
} 

- (void) cancelCountdown 
{ 
    [self.countdownTimer invalidate]; 
    self.countdownTimer = nil; 
} 

- (void) timerTick: (NSTimer *) aTimer 
{ 
    NSDate * endDate = [timer userInfo]; 
    NSDate * now = [NSDate date]; 

    // have we passed the end date? 
    if ([endDate laterDate: now] == now) 
    { 
     // show alert 
     [self cancelCountdown]; 
     return; 
    } 

    // otherwise, compute units & show those 
    NSUInteger units = NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit; 

    NSDateComponents * comps = [[NSCalendar currentCalendar] components: units 
                   fromDate: [NSDate date] 
                   toDate: endDate 
                   options: 0]; 
    [self.clockView setHours: comps.hour 
        minutes: comps.minute 
        seconds: comps.second]; 
} 
+0

しかし、ユーザーがたとえば細胞? – LuckyLuke

+0

また、NSEventTrackingRunLoopModeまたはUIEventTrackingRunLoopModeにタイマーをインストールすると、入力イベントの追跡が行われても起動します。 –

+0

私はそれのような定数を見つけることはありません。 – LuckyLuke

1

メインスレッドでタイマーを作成するだけで、セカンダリスレッドでタイマーを実行する必要はありません。あなたは、二次スレッドからGUIを更新してはいけません。はい、performSelectorInMainThreadを使うことができますが、なぜ気にしませんか?あなたのタイマーが "あまりにも頻繁に"呼ばれていない限り、メインスレッドにすべてを置くだけで、パフォーマンスは正常になります。

+0

私がメインスレッド(時計であるため毎秒更新する)にタイマーを置き、ユーザーがタッチで滑走路をブロックすると、時計が停止します。 – LuckyLuke