查看不更新

时间:2009-10-03 23:13:40

标签: iphone objective-c multithreading

有点新的iPhone编程并正在尝试线程

- (void)viewDidLoad {
    [super viewDidLoad];

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

- (void)changeMain{
    NSAutoreleasePool* arp = [[NSAutoreleasePool alloc] init];

    for (int i = 0; i < 1000000; i++) {
        [mainValue setText:[NSString stringWithFormat:@"%d",i]];
        [self.view setNeedsDisplay];    
    }

    [arp release];
}
- (void)changeThread{
    NSAutoreleasePool* arp = [[NSAutoreleasePool alloc] init];

    for (int i = 0; i < 1000000; i++) {
        [threadValue setText:[NSString stringWithFormat:@"%d",i]];
        [self.view setNeedsDisplay];
    }

    [arp release];
}

mainValue和threadValue都只是UILabels。我希望这个运行并看到两个标签都运行到999999但是它开始时的数字很低(当我初步刷新时我假设它是什么),暂停一下,然后更新到999999.我在想屏幕只是不爽快。

这是对的吗?我做错了吗?

4 个答案:

答案 0 :(得分:1)

setNeedsDisplay消息会触发重绘,但只会在主线程下次活动时发生。因此,您的侧线程会触发一百万次重绘,但它们会排队等候。一旦主线程继续,它就会将所有请求“折叠”为一次重绘。

很可能setNeedsDisplay只设置一个在主循环的每次运行期间检查一次的标志,因此将其设置为1000000为true不会影响任何内容。尝试让“工作线程”在每次迭代后保持睡眠状态,以便为主线程重新绘制一些时间。

答案 1 :(得分:1)

  1. 你必须在主线程中执行任何Cocoa Touch操作,在其他情况下,结果是不可预测的。
  2. 您无需手动拨打setNeedsDisplay
  3. 所以我建议使用以下结构:

    [threadValue performSelectorOnMainThread:@selector(setText:) withObject:[NSString stringWithFormat:@"%d",i] waitUntilDone:YES];
    

    附加说明: 1. 100000次运行可以溢出主线程队列,因此某些值将消失 2.您也可以使用waitUntilDone:NO

答案 2 :(得分:1)

不要将for()用于动画。 for将在同一“框架”中处理。也许只有一个ivar i而在changeMain你可以有if (i<10000) { mainValue.text = [NSString stringWithFormat:@"%d",i]; i++;}或类似的东西。这样setText每个“帧”只发生一次。

答案 3 :(得分:0)

我不确定这是否有效,但您可以尝试强制setNeedsDisplay方法在主线程上执行,例如使用[self performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone:YES]。这应该(希望,我没有测试它!)每次增量后更新视图。您也可以尝试设置waitUntiDone:NO,但我不确定会发生什么。

See here