2

我很确定这真的很简单,我只是遗漏了一些明显的东西。我有一个应用程序需要从 Web 服务下载数据以显示在 UITableView 中,如果操作需要超过 X 秒才能完成,我想显示 UIAlertView。所以这就是我所得到的(为简洁起见):

MyViewController.h

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

@property (nonatomic, retain) NSTimer *timer;

我的视图控制器.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

我认为调度计时器和在同一个线程上进行阻塞调用存在问题。在阻塞调用完成之前,运行循环不能触发计时器。

我建议你分离一个线程来执行长操作。长操作完成后,回调主线程以使计时器无效。

注意:在调度的同一线程上使计时器无效很重要。

- (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()线程上,并且相关的运行循环永远没有机会调用计时器的选择器。

如果您在-doSomething不阻塞线程的情况下进行真正的工作,例如对 Web 服务的非阻塞调用,它将按预期工作。然而,阻塞调用必须在不同的线程中完成,这样主运行循环就不会被阻塞。

于 2010-06-02T22:02:31.243 回答