同步多个UITableView实例的滚动位置 [英] Syncing the scroll position of multiple UITableView instances
问题描述
我有一个项目,我需要在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屋!