2

私はこれが本当に単純であるとかなり確信しています、そして私はただ明白な何かを逃しています。UITableViewに表示するためにWebサービスからデータをダウンロードする必要があるアプリがあり、操作の完了にX秒以上かかる場合はUIAlertViewを表示したいと思います。だからこれは私が持っているものです(簡潔にするために簡略化されています):

MyViewController.h

@interface MyViewController : UIViewController
        <UITableViewDelegate, UITableViewDataSource> {
    NSTimer *timer;
}

@property (nonatomic, retain) NSTimer *timer;

MyViewController.m

@implementation MyViewController

@synthesize timer;

- (void)viewDidLoad {
    timer = [NSTimer scheduledTimerWithTimeInterval:20
          target:self
        selector:@selector(initializationTimedOut:)
        userInfo:nil
         repeats:NO];

    [self doSomethingThatTakesALongTime];
    [timer invalidate];
}

- (void)doSomethingThatTakesALongTime {
    sleep(30); // for testing only
    // web service calls etc. go here
}

- (void)initializationTimedOut:(NSTimer *)theTimer {
    // show the alert view
}

私の問題は、タイマーがカウントを続けている間に呼び出しがブロックされることを期待していることです。タイマーがカウントダウンを完了する前に呼び出しが終了すると、スレッドの制御がどこ[self doSomethingThatTakesALongTime]に戻ってタイマーがキャンセルされるかを考えています。 。明らかに、タイマー/スレッドがどのように機能するかについての私の理解は、コードの記述方法によってタイマーがオフになることはないため、ここでは欠陥があります。ただし、を削除すると、削除されます。viewDidLoad[timer invalidate][timer invalidate]

4

3 に答える 3

3

タイマーのスケジューリングと同じスレッドでのブロッキング呼び出しの実行に問題があると思います。ブロッキング呼び出しが完了するまで、run-loopはタイマーを起動できません。

長い操作を実行するには、スレッドを切り離すことをお勧めします。長い操作が終了したら、メインスレッドにコールバックしてタイマーを無効にします。

注:スケジュールされたのと同じスレッドでタイマーを無効にすることが重要です。

- (void)viewDidLoad {
    timer = [NSTimer scheduledTimerWithTimeInterval:20
          target:self
        selector:@selector(initializationTimedOut:)
        userInfo:nil
         repeats:NO];

    [NSThread detachNewThreadSelector:@selector(doSomethingThatTakesALongTime:) toTarget:self withObject:nil];
}

- (void)doSomethingThatTakesALongTime:(id)arg {
    sleep(30); // for testing only
    // web service calls etc. go here
    [self performSelectorOnMainThread:@selector(invalidate) withObject:nil waitUntilDone:NO];
}

- (void)invalidate {
    [timer invalidate];
}

- (void)initializationTimedOut:(NSTimer *)theTimer {
    // show the alert view
}
于 2010-06-02T22:02:29.090 に答える
0

使ってみました[NSThread sleepforTimeInterval:30];か?

于 2010-06-02T21:57:31.677 に答える
0

sleep()メインスレッドで発生し、関連する実行ループはタイマーのセレクターを呼び出す機会がありません。

-doSomethingWebサービスへの非ブロック呼び出しなど、スレッドをブロックしない実際の作業を行う場合は、期待どおりに機能します。ただし、呼び出しのブロックは、メインの実行ループがブロックされないように、別のスレッドで実行する必要があります。

于 2010-06-02T22:02:31.243 に答える