2009-10-03 91 views
0

还挺新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。我在想屏幕只是不令人耳目一新。

这是正确的吗?我做错了吗?

回答

1
  1. 你必须在主线程中执行任何可可触摸操作,在其他情况下,结果是不可预知的。
  2. 您不必手动拨打setNeedsDisplay

所以我建议使用下面的结构:

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

其他注意事项:1。 运行100000可以溢出主线程队列,以便某些值会消失 2.可以使用waitUntilDone:NO

+0

工作就像一个魅力。谢谢! – ACBurk 2009-10-04 18:27:36

1

setNeedsDisplay消息触发重绘,但它只发生在主线程下次启动时。所以你的边线程会触发一百万次重画,但它们已经排队。一旦主线程继续,它将所有请求“合并”为一个重绘。

最有可能的setNeedsDisplay只设置一个标志,在主循环的每次运行期间检查一次,因此将其设置为1000000并不影响任何内容。尝试让“工作线程”在每次迭代后进入休眠状态,让主线程有时间重绘。

0

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

See here

1

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