在iOS开发中,苹果其实已经帮你实现了点击状态栏回到顶部这个功能,但我们在开发中会遇到点击不能回到顶部.其实这都和
ScrollView中的一个属性scrollsToTop有关,我们先看看苹果关于这个属性的解释:
// When the user taps the status bar, the scroll view beneath the touch which is closest to the status bar will be scrolled to top, but only if its `scrollsToTop` property is YES, its delegate does not return NO from `shouldScrollViewScrollToTop`, and it is not already at the top. // On iPhone, we execute this gesture only if there's one on-screen scroll view with `scrollsToTop` == YES. If more than one is found, none will be scrolled. @property(nonatomic) BOOL scrollsToTop __TVOS_PROHIBITED; // default is YES.
其实根据苹果说的,如果当前窗口上,如果你不止一个scrollView的话,因为苹果不知道当你点击状态栏的时候,不知道让哪一个scrollView回到顶部,就会默认把这个属性赋值为NO;
其实解决方法很简单,你确定好点击状态栏你需要哪个scrollView回到顶部,把他的属性赋值为YES,其他的scrollView 的这个属性赋值为NO.这样就可以利用系统的这个功能.
scrollsToTop属性,苹果内部实现原理:
思想: 苹果的底层就是使用递归,遍历当前窗口上所有的View,找到那个scrollView,并让它回到顶部,这也就解释了,为什么当前窗口上,如果有几个scrollView的话,scrollsToTop属性,会失效.
假设我现在需要拿到窗口上的这个tableView,实现要它回到顶部
1.获取主窗口,调用递归函数
// 遍历窗口所有的子控件,看有没有tableView UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow; // 获取窗口的所有子控件fetchTableView就是递归方法 UITableView *tableView = [self fetchTableView:keyWindow];
2.递归方法实现
若是找到想要找到的tableView,就返回,否则就返回空
- (UITableView *)fetchTableView:(UIView *)view { //以当前view为父控件,查找子控件 for (UIView *childView in view.subviews) { if ([childView isKindOfClass:[UITableView class]]) { return (UITableView *)childView; } return [self fetchTableView:childView]; } return nil; }
还有一种方法,在状态栏的一样的位置外面加一个window窗口
static XMGStatusWindow *_statusWindow; + (void)show { XMGStatusWindow *statusWindow = [[XMGStatusWindow alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 20)]; //将这个window优先级设为最高 statusWindow.windowLevel = UIWindowLevelAlert; statusWindow.backgroundColor = [UIColor clearColor]; statusWindow.rootViewController = [[UIViewController alloc] init]; statusWindow.hidden = NO; _statusWindow = statusWindow; // 当程序有多个窗口的时候,状态栏自动隐藏 // 恢复状态栏显示 [UIApplication sharedApplication].statusBarHidden = NO; }
注: 在iOS10之后,苹果为了提高collectionView性能,苹果加了预加载,会同时在窗口上加载三个collectionView的cell,也就会导致你会在窗口上拿到三个cell.解决这个问题只需设置:
collectionView.prefetchingEnabled = NO;