大神笔记-学习

iOS11全局适配automaticallyAdjustsScr

2017-10-20  本文已影响253人  冯里

一、bug展示

在iOS 11之下

Simulator Screen Shot - iPhone 8 Plus - 2017-10-20 at 09.32.46.png

UITableView创建方式如下:

self.automaticallyAdjustsScrollViewInsets = NO;
UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
[self.view addSubview:tableView];
[tableView setContentInset:UIEdgeInsetsMake(64, 0, 0, 0)];
tableView.backgroundColor = [UIColor redColor];
tableView.delegate = self;
tableView.dataSource = self;

二、bug原因

在新版iOS11中automaticallyAdjustsScrollViewInsets方法被废弃,我们需要使用UIScrollView的 contentInsetAdjustmentBehavior 属性来替代它.
我们先来看看contentInsetAdjustmentBehavior这个枚举值:

typedef NS_ENUM(NSInteger, UIScrollViewContentInsetAdjustmentBehavior) {
    UIScrollViewContentInsetAdjustmentAutomatic, // Similar to .scrollableAxes, but for backward compatibility will also adjust the top & bottom contentInset when the scroll view is owned by a view controller with automaticallyAdjustsScrollViewInsets = YES inside a navigation controller, regardless of whether the scroll view is scrollable
    UIScrollViewContentInsetAdjustmentScrollableAxes, // Edges for scrollable axes are adjusted (i.e., contentSize.width/height > frame.size.width/height or alwaysBounceHorizontal/Vertical = YES)
    UIScrollViewContentInsetAdjustmentNever, // contentInset is not adjusted
    UIScrollViewContentInsetAdjustmentAlways, // contentInset is always adjusted by the scroll view's safeAreaInsets
} API_AVAILABLE(ios(11.0),tvos(11.0));

如果需要适配项目中self.automaticallyAdjustsScrollViewInsets = NO;,那么设置为UIScrollViewContentInsetAdjustmentNever

三、全局适配

对于一个iOS 11之前的项目,想要适配该特性,如果在每个视图控制器中去设置将是一个庞大的工作量,所以在这里通过分类的方式全局添加该特性,先贴上源码:
创建UIViewController的一个分类

#import "UIViewController+FLInsert.h"

@implementation UIViewController (VFInsert)

+ (void)load {
    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        Class class = [self class];
        SEL originalSelector = @selector(viewWillAppear:);
        SEL swizzledSelector= @selector(FL_viewWillAppear:);

        Method originalMethod = class_getInstanceMethod(class,originalSelector);
        Method swizzledMethod = class_getInstanceMethod(class,swizzledSelector);
        method_exchangeImplementations(originalMethod,swizzledMethod);

    });
}

- (void)FL_viewWillAppear:(BOOL)animated {

    [self FL_viewWillAppear:animated];
    UIScrollView *scrollView = nil;
    for (UIView *view in self.view.subviews) {
        if ([view isKindOfClass:[UITableView class]] || [view isKindOfClass:[UICollectionView class]]) {
            scrollView = (UIScrollView *)view;
            break;
        }
    }
    if (!self.automaticallyAdjustsScrollViewInsets) {
        if (@available(iOS 11.0, *)) {
            scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
        }
    }
    else {
        if (@available(iOS 11.0, *)) {
            scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentAutomatic;
        }
    }
}

- (void)FL_setAutomaticallyAdjustsScrollViewInsets:(BOOL)automaticallyAdjustsScrollViewInsets {

    [self FL_setAutomaticallyAdjustsScrollViewInsets:automaticallyAdjustsScrollViewInsets];

}

@end

在UIViewController的分类中使用运行时进行方法交换,使用FL_viewWillAppear:(BOOL)animated方法替换原有viewWillAppear:(BOOL)animated方法,同时在FL_viewWillAppear:(BOOL)animated方法再调用viewWillAppear:(BOOL)animated方法,保证系统viewWillAppear:(BOOL)animated方法正常运行。然后在FL_viewWillAppear:(BOOL)animated方法做需要做的事情,找到需要视图控制中的UIScrollView,根据automaticallyAdjustsScrollViewInsets属性给UIScrollView设置对应的contentInsetAdjustmentBehavior属性值。

上一篇 下一篇

猜你喜欢

热点阅读