同步多个UITableView实例的滚动位置 [英] Syncing the scroll position of multiple UITableView instances

查看:123
本文介绍了同步多个UITableView实例的滚动位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个项目,我需要在iPad上的同一视图中显示多个 UITableView 个实例。它们也恰好是旋转的,但我相当肯定这是无关紧要的。用户应该不知道视图由多个表视图组成。因此,我想这样做,以便当我滚动一个tableview时,其他人同时滚动它。

I have a project in which I need to display multiple UITableView instances inside the same view on the iPad. They also happen to be rotated, but I'm fairly certain this is irrelevant. The user should be unaware that the view is made up of multiple table views. Therefore, I'd like to make it so that when I scroll one tableview, the others scroll with it at the same time.

因为 UITableView UIScrollView 的子类,我想我可以处理 UIScrollViewDelegate 方法并传递它们所有的tableviews。不幸的是,虽然我可以捕获一些事件,但方法调用粒度不够好,而且我无法将这些消息传递给其他tableviews。我能得到的最接近的是实现 -scrollViewDidScroll:,然后在每个tableview上调用 -setContentOffset:animated 。如果我尝试为所有可能的情况发送此消息,我最终会锁定,因为 -scrollViewDidScroll 正在调用我的 -setContentOffset:animated 来电,所以我最终冻结了。无论如何,如果我通过仅使用此方法检测一个tableview上的滚动然后将其传递到其他tableviews来消除锁定,我发现虽然其他tableviews最终滚动到同一位置,但它们落后于第二个或两个。

Because UITableView is a subclass of UIScrollView, I figured I could handle UIScrollViewDelegate methods and pass them along to all of the tableviews. Unfortunately, while I can capture some events, the method call granularity is not fine enough and I'm having trouble passing along these messages to the other tableviews. The closest I can get is implementing -scrollViewDidScroll: and then calling -setContentOffset:animated on every tableview. If I attempt to send this message for all potential cases, I end up locking up because -scrollViewDidScroll is getting called for my -setContentOffset:animated calls, so I end up freezing up. Regardless, if I eliminate the lockup by only using this method to detect scrolling on one tableview and then passing it on to the other tableviews, I find that while the other tableviews do end up scrolling to the same location, They lag behind a second or two.

这是一个示例项目我创建了。

如果没有子类化 UITableView ,我怎么能实现这种行为?

How can I implement this behavior without subclassing UITableView?

推荐答案

您可以通过直接观察 contentOffset 来解决回调粒度问题。在 viewDidLoad 中,在需要同步的每个表视图上设置KVO:

You can get around the callback granularity issue by observing contentOffset directly. In viewDidLoad, set up KVO on each of the table views you need to synchronize:

for(UITableView *view in self.tableViewCollection)
{
    [view addObserver:self 
           forKeyPath:@"contentOffset" 
              options:NSKeyValueObservingOptionNew 
              context:NULL];
}

然后,当您观察到更改时,暂时取消观察,更新另一个表视图的偏移量,并重新开启观察。

Then, when you observe changes, temporarily unhook the observation, update the other table views' offsets, and turn observation back on.

- (void)observeValueForKeyPath:(NSString *)keyPath 
                      ofObject:(id)object 
                        change:(NSDictionary *)change 
                       context:(void *)context
{
    static BOOL isObservingContentOffsetChange = NO;
    if([object isKindOfClass:[UITableView class]] 
       && [keyPath isEqualToString:@"contentOffset"])
    {
        if(isObservingContentOffsetChange) return;

        isObservingContentOffsetChange = YES;
        for(UITableView *view in self.tableViewCollection)
        {
            if(view != object)
            {
                CGPoint offset = 
                 [[change valueForKey:NSKeyValueChangeNewKey] CGPointValue];
                view.contentOffset = offset;
            }
        }
        isObservingContentOffsetChange = NO;
        return;
    }

    [super observeValueForKeyPath:keyPath 
                         ofObject:object 
                           change:change 
                          context:context];
}

这可能会变得更漂亮,但它可以解决这个问题。

This can probably be made prettier, but it gets the idea across.

这篇关于同步多个UITableView实例的滚动位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆