2009-07-29 71 views
1

我有一个分段控制被用作切换。当切换时,我在表格视图中切换了一堆内容,这些内容占用了很少但很明显的时间(插入/删除表格视图中的部分,动画更改等)。我希望分段控制立即响应选择。所以在我的行动处理代码分段控制的UIControlEventValueChanged事件,我做了以下内容:保持一个UISegmentedControl(等)响应

- (IBAction)groupingChanged:(id)sender { 
    UISegmentedControl *seg = sender; 
    [tableModel toggleOn:[seg selectedSegmentIndex] == ToggleOnIndex]; 
    [self performSelectorOnMainThread:@selector(updateGrouping) 
          withObject:nil 
         waitUntilDone:NO]; 
} 

其中updateGrouping是:

- (void)updateGrouping { 
    MXAssertMainThread(); 

    [tableView beginUpdates]; 
    ... several table updates 
    [tableView endUpdates]; 
} 

设置waitUntilDone:NO允许groupingChanged方法来完成updateGrouping被调用之前,但这似乎不足以重新绘制视图。分段控制一直持续到表完成更新,然后切换。

于是,我就修改groupingChanged:创建一个线程,像这样的更新:

- (void)delayed { 
    [self performSelectorOnMainThread:@selector(updateGrouping) 
          withObject:nil 
         waitUntilDone:NO]; 
} 

- (IBAction)groupingChanged:(id)sender { 
    UISegmentedControl *seg = sender; 
    [tableModel toggleOn:[seg selectedSegmentIndex] == ToggleOnIndex]; 
    [self performSelectorInBackground:@selector(delayed) withObject:nil]; 
} 

这确实工作。分段控制立即切换,表格随即显示。但我对结果一点都不信任。这只是在新线程启动时给主线程一个暂缓的副作用吗?这只是我需要如何排队更新到用户界面?这显然很不好。我希望有人在这种情况下有更好的模式。

回答

1

如果你只是想确保分段控制真正快速重新绘制,我可能不会潜入线程。

相反,我只是设置一个像0.1这样的低值的计时器,并且应该足以让控制更新,而不会对用户造成任何明显的延迟。

当我有很多工作要做但需要快速的UI更新时,我已经使用了这个。

还是有点“黑客”,但没有引入线程。

所以......

- (IBAction)groupingChanged:(id)sender { 
    UISegmentedControl *seg = sender; 
    [tableModel toggleOn:[seg selectedSegmentIndex] == ToggleOnIndex]; 
    [NSTimer scheduledTimerWithTimeInterval:0.1 
            target:self 
            selector:@selector(updateGrouping) 
            userInfo:nil 
            repeats:NO];  

} 
+0

这消除了临时线程,所以这是一个改进,但我拒绝相信没有常见的非hacky模式。 – 2009-07-29 17:54:18

2

认为它这样 - 你所做的一切通常做在主线程,包括用户界面的更新。

因此,在您的原始代码中,更新表视图的代码在对该段进行了UI更新的代码之前已达到。

因此,您给予主线程一个中断允许更多时间完成UI更新是正确的,因为主线程被允许在后台线程处理表更新时完成UI更新。

另一种可以尝试的方法是使用performSelector:withObject:afterDelay,延迟时间为0.0(这允许主线程在继续选择器之前处理其他事情)。它可能在performSelectorOnMainThread没有的地方工作,因为即使它们最终做了非常相似的事情,它也可能更直接。

0

我遇到了同样的问题,并通过继承UISegmentedControl来创建Delayed UISegmentedControl来解决此问题。

在延迟控制中,我覆盖了addTarget:action:forControlEvents:以捕获目标&的操作。然后,当发生段事件时,我运行NSTimer以在设置的延迟后启动捕获的目标&操作。其结果是,在UI被更新,以显示该段点击,我可以使用DelayedUISegmentedControl就像我会一个UISegmentedControl:

// Follows all normal initialization patterns of UISegmentedControl 
UISegmentedControl *segmentedControl = [[DelayedUISegmentedControl alloc] 
    initWithItems:[NSArray arrayWithObjects: @"First", @"Second", nil]]; 

// Adds a delay to the selector; default is 0.25 
[segmentedControl addTarget:self action:@selector(segmentAction:) 
    forControlEvents:UIControlEventValueChanged]; 

如果你想下载我已经开源了它google code控制。