3

我目前正在开发的应用程序在多个不同的场景中同时具有多个UITableView/实例。UIScrollView

当多个实例具有scrollsToTop == YES时,点击状态栏时只有一个实例实际滚动到顶部。

我正在寻找最简单的解决方案,以确保只有一个滚动视图实例(最近一个)具有scrollsToTop == YES.

我想出了一个使用方法 swizzling的解决方案,我不确定它是否是最好的解决方案。我想知道解决这个问题的任何其他方法或任何类型的建议。

这是我的解决方案:

  1. createUIScrollView的类别添加方法mySetScroolsToTop:

    -(void)mySetScrollsToTop:(BOOL)scrollsToTop{
        [self mySetScrollsToTop:scrollsToTop];
    
        if(scrollsToTop){
            [[NSNotificationCenter defaultCenter] 
                postNotificationName:SetScrollsToTopNotification object:self];  
        }
    
    }
    
    -(void)scrollsToTopIsSet:(NSNotification *)notification{
    
        if(notification.object != self){
            [self mySetScrollsToTop:NO];
        }
    }
    
  2. UIViewController使用以下方法创建类别

    -(void)myViewDidLoad{
    
     self findScrollViewAndObserveScrollToTopNotification:self.view];
    
     [self myViewDidLoad];
    
    }
    
    
    -(void)findScrollViewAndObserveScrollToTopNotification:(UIView *)view{
    
     for(UIView* v in view.subviews){
    
      if([v isKindOfClass:[UIScrollView class]]){
    
         [[NSNotificationCenter defaultCenter] addObserver:v
                                                 selector:@selector(scrollsToTopIsSet:)
                                                     name:kSetScrollsToTopNotification
                                                   object:nil];
      }
    
     [self findScrollViewAndObserveScrollToTopNotification:v];
    
     }
    }
    
    -(void)myDealloc{
    
     [[NSNotificationCenter defaultCenter] removeObserver:self];
     [self myDealloc];
    
    }
    
  3. 使用swizzling 方法交换mySetScrollsToTop, myViewDidLoad, 和myDealloc原始的。

编辑:

抱歉,如果我的问题不清楚。

每个viewcontroller都有多个tableViews,它们由用户切换,例如分段控制。选择A tableView/时scrollView,我想设置其scrollToTop = YES并要确保将所有其他scrollViewsscrollsToTop设置为否。

我正在开发的应用程序有左侧菜单栏,如 Facebook 应用程序,它有一个UITableView内部和一个选项卡栏,每个选项卡都包含一个UITableView显示在菜单上的选项卡UITableView。在右侧窗格中,还有UITableView可以使用分段控制器进行选择和切换的 s。我想确保只有一个表视图处于活动状态scrollsToTop

编辑2:

我打印出窗口的子视图并且不包含我的视图:

2013-05-16 10:44:01.416  UIView
2013-05-16 10:44:01.417  UILayoutContainerView
2013-05-16 10:44:01.417  UINavigationTransitionView
2013-05-16 10:44:01.417  UIView
2013-05-16 10:44:01.417  UILayoutContainerView
2013-05-16 10:44:01.417  UINavigationTransitionView
2013-05-16 10:44:01.417  UINavigationBar
2013-05-16 10:44:01.417  _UINavigationBarBackground
2013-05-16 10:44:01.417  UIImageView
2013-05-16 10:44:01.418   UIButton
2013-05-16 10:44:01.418  UIImageView
2013-05-16 10:44:01.418  UIImageView

Edit3: 我实现了 swizzling 并且它有效。但是,我仍然接受任何更好的解决方案。谢谢!

4

2 回答 2

3

scrollsToTop默认YES为所有滚动视图。

使您的视图控制器成为所有滚动视图的委托,然后实现:

- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView {
    return (scrollView == <the only scroll view you want to scroll to the top>);
}

当顶部栏被点击时,scrollViewShouldScrollToTop:将被调用并且你应该为你想要滚动的滚动视图返回 YES。

编辑更新的问题:

这将满足您的要求。

// Set `scrollsToTop` to false for every scroll view of every view controller
for (UIViewController *controller in self.navigationController.viewControllers)
    for (id obj in controller.view.subviews)
        if ([obj isKindOfClass:[UIScrollView class]])
            ((UIScrollView*)obj).scrollsToTop = NO;

// Set `scrollsToTop` to true for whichever scroll view is currently visible
activeScrollView.scrollsToTop = YES;
于 2013-05-15T23:59:48.707 回答
1

您可以使用以下方法:

- (void) disableScrollToTopExceptScrollView:(UIScrollView*) scrollView
{
    [self internalDisableScrollViewsExceptScrollView:scrollView rootView:self.window];
}

- (void) internalDisableScrollViewsExceptScrollView:(UIScrollView*) scrollView rootView:(UIView*) root
{
    NSArray* subviews = root.subviews;
    for(UIView* view in subviews)
    {
        if([view isKindOfClass:[UIScrollView class]])
        {
           if(view==scrollView)
           {
               [(UIScrollView*)view setScrollsToTop:YES];
           }
            else
            {
                [(UIScrollView*)view setScrollsToTop:NO];
            }
        }
        [self internalDisableScrollViewsExceptScrollView:scrollView rootView:view];
    }
}

例如,在 AppDelegate 类中实现它们,并从您的应用程序中的任何点调用 - 这将禁用应用程序视图层次结构中的所有滚动视图,除了您传递的那个。

于 2013-05-16T04:43:41.867 回答