IOS11适配

作者: coderhlt | 来源:发表于2017-09-30 15:07 被阅读153次

    说明:首先感谢各位iOS界的大神们,写了好多iOS11文章可以参考,我这里负责搜集整理下,并结合自己的实践记录一下关于iOS11的常用适配,一切为开发更简单更高效。

    一、定位失效

    苹果新增加了一项NSLocationAlwaysAndWhenInUseUsageDescription隐私权限,原有的 NSLocationAlwaysUsageDescription 被降级为 NSLocationWhenInUseUsageDescription。
    解决方案:在infoplist文件里里增加NSLocationAlwaysAndWhenInUseUsageDescription 和 NSLocationWhenInUseUsageDescription两个,如果需要支持iOS10的话,增加NSLocationAlwaysUsageDescription

    二、相册权限

    ios11使用相机功能,原有项目crash。
    ios11之后苹果对相册的隐私权限作了调整,原来的NSPhotoLibraryUsageDescription 调整成了NSPhotoLibraryAddUsageDescription
    解决方案:在infoplist文件里添加NSPhotoLibraryAddUsageDescription

    三、ScrollView相关控件,比如tableview、webView、collectionView等控件顶部会有一定距离的偏移。

        webview.frame=CGRectMake(0, 0, 375, 667);
        [self.view addSubview:webview];
        [webview loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.baidu.com"]]];
    

    运行后如图:未充满屏幕下移了20


    WechatIMG5.jpeg

    原因是:iOS 11中Controller的automaticallyAdjustsScrollViewInsets属性被废弃了,决定scrollview的内容与边缘距离的是adjustedContentInset属性,而不再是contentInset。当视图被状态栏导航条被覆盖,系统会自系统自动调整了SafeAreaInsets值,进而影响adjustedContentInset值,会对adjustedContentInset值进行了调整,所以导致tableView的内容到边缘的距离发生了变化,导致下移了20pt。

    解决方案:关闭系统的自动调整计算
    webview.scrollView.contentInsetAdjustmentBehavior=UIScrollViewContentInsetAdjustmentNever
    

    四、tableview相关

    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.view.backgroundColor=[UIColor redColor];
        self.view.backgroundColor=[UIColor redColor];
        UITableView *tableview=[[UITableView alloc]initWithFrame:CGRectMake(0, 0, 375, 667) style:UITableViewStyleGrouped];
        tableview.delegate=self;
        tableview.dataSource=self;
        [self.view addSubview:tableview];
    }
    
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
        return 3;
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{//设置每组里有多少行
        return 1;
    }
    //去除头部的默认间距
    - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
        return 0.01;
    }
    //去除尾部的默认间距
    - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
        return 0.01;
    }
    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
        static NSString * chongzu =@"Cell";//重用机制标识
        
        UITableViewCell* cell =[tableView dequeueReusableCellWithIdentifier:chongzu];//根据重用标r识,到重用池找对应的cell
        if (cell==nil) {
            cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:chongzu];//创建一个cell,设置其样式以及其标识
        }
        cell.backgroundColor=[UIColor redColor];
        cell.textLabel.text=[NSString stringWithFormat:@"%li",(long)indexPath.row];
        return cell;//将设置好的cell返回
    }
    @end
    

    老铁们应该都知道默认tableView开头和结尾是有间距的,在开发中不需要这样的间距,我们通常会返回0.01这样很小的头部和尾部视图高度,在ios11之前是没问题的,然我们在ios11运行一下发现并没卵用。
    原因分析:
    ios11后estimatedSectionHeaderHeight ,estimatedSectionFooterHeight
    这些估算高度默认值都是UITableViewAutomaticDimension,估算机制处于开启状态,代码中我们只返回高度却没有返回对应的视图,这两个返回高度的代理方法是不会执行的。只要返回对应的视图就好了。
    解决方案:
    方案一 :返回对应的视图

    -(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
        return nil;
    }
    - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{
        return nil;
    }
    

    方案二:关闭估算机制

        tableview.estimatedSectionHeaderHeight=0;
        tableview.estimatedSectionFooterHeight=0;
    

    有时你也会发现cell莫名其妙的自适应高度了,那是因为ios11后tableview的行高默认不在是44了而是UITableViewAutomaticDimension是自动计算的,如果你需要自适应只需要重设rowheight的值就行了。
    五、关于自定义返回按钮

      1. 替换系统返回按钮图片并隐藏返回按钮文字
    +(void)initialize{
        
        UIImage *backButtonImage = [[UIImage imageNamed:@"back"]
                                    resizableImageWithCapInsets:UIEdgeInsetsMake(0, 18, 0, 0)];
        [[UIBarButtonItem appearance] setBackButtonBackgroundImage:backButtonImage
                                                          forState:UIControlStateNormal
                                                        barMetrics:UIBarMetricsDefault];
        
        [[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -60)
                                                             forBarMetrics:UIBarMetricsDefault];
    }
    

    ios11以下运行正常显示:

    BA95CE00-E9EA-4ECD-996D-6E29D71AE818.png

    而ios11以上运行返回图片不居中


    9C5D58E3-853D-4456-A7D2-94AE25BEF98F.png

    原因分析:iOS 11 中setBackButtonTitlePositionAdjustment:UIOffsetMake没法把按钮移出navigation bar。

    解决方法是设置navigationController的backIndicatorImage和backIndicatorTransitionMaskImage

    +(void)initialize{
            UIImage *backButtonImage = [[UIImage imageNamed:@"back"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
             [UINavigationBar appearance].backIndicatorImage = backButtonImage;
             [UINavigationBar appearance].backIndicatorTransitionMaskImage = backButtonImage;
           //将返回文字去掉
            [[UIBarButtonItem appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor clearColor]} forState:UIControlStateNormal];
    }
    
    

    或者这样

    +(void)initialize{
            UIImage *backButtonImage = [[UIImage imageNamed:@"back"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
             [UINavigationBar appearance].backIndicatorImage = backButtonImage;
             [UINavigationBar appearance].backIndicatorTransitionMaskImage = backButtonImage;
           [[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(-300, 0) forBarMetrics:UIBarMetricsDefault];
    }
    
    
    • 2.自定义UIBarButtonItem
      在iOS7之后,我们在设置UINavigationItem的leftBarButtonItem,rightBarButtonItem的时候都会造成位置的偏移,虽然不大,但是跟UI的设计或者国人的习惯有点区别,通常我们添加一个宽度为负值的UIBarButtonItem
        UIButton *btn=[[UIButton alloc]init];
        btn.frame=CGRectMake(0, 0, 60, 40);
        [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        [btn setTitle:@"设置" forState:UIControlStateNormal];
        UIBarButtonItem *item=[[UIBarButtonItem alloc]initWithCustomView:btn];
        UIBarButtonItem *fixedSpace = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
        fixedSpace.width =-20;
        self.navigationItem.rightBarButtonItems=@[fixedSpace, item];
    

    但是这些在iOS 11中都无效了!,在ios11后改动相当大的就是导航栏的部分,在原来的已经复杂的不要的图层中又新增了新的图层.那么我这里解决方案是自定义个NavigationBar。
    参考:https://www.jianshu.com/p/5ec6e0cc5036

    @implementation HLTNavigationBar
    
    - (void)layoutSubviews{
        [super layoutSubviews];
        NSLog(@"%@",self.subviews);
        for (UIView *view in self.subviews) {//适配ios11
            if ([NSStringFromClass(view.class) containsString:@"ContentView"]) {
                view.layoutMargins = UIEdgeInsetsZero;//可修正iOS11之后的偏移
                NSLog(@"%@",view.subviews);
            }else{//适配iosios10
                if ([view isKindOfClass:[Backbutton class]]) {
                    CGRect frame = view.frame;
                    frame.origin.x=0;
                    view.frame=frame;
                }
            }
        }
    }
    

    六、ios11的滑动删除
    IOS11新增了两个代理方法,可以给这些按钮添加图片了。如果实现了新增的Swipe actions的代理方法将会取代(tableView: editActionsForRowAtIndexPath:)
    1.向左滑动在右边显示(常用的左滑删除)

    - (UISwipeActionsConfiguration *)tableView:(UITableView *)tableView trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath{
        /* UIContextualActionStyle有两种类型:
        UIContextualActionStyleNormal,//置顶、删除、已读都可以使用该类型
        UIContextualActionStyleDestructive//删除类型可使用,从左到右一直滑cell,不用点击删除按钮就可以直接执行删除操作
        */
        //1.创建UIContextualAction对象
        UIContextualAction *deleteRowAction = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleDestructive title:@"delete" handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) {
            //[self.titleArr removeObjectAtIndex:indexPath.row];
            completionHandler (YES);
        }];
        //2.给滑动按钮添加背景、图片
        deleteRowAction.image = [UIImage imageNamed:@"icon_del"];
        deleteRowAction.backgroundColor = [UIColor blueColor];
        
       //3.返回滑动按钮
        UISwipeActionsConfiguration *config = [UISwipeActionsConfiguration configurationWithActions:@[deleteRowAction]];
        return config;
    }
    

    2、左、右都可以滑
    左滑是系统删除按钮,右滑可以是自定义的滑动按钮

    - (UISwipeActionsConfiguration *)tableView:(UITableView *)tableView leadingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath{
        UIContextualAction *deleteRowAction = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleNormal title:@"取消" handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) {
            //[self.titleArr removeObjectAtIndex:indexPath.row];
            completionHandler (YES);
        }];
        deleteRowAction.image = [UIImage imageNamed:@"icon_del"];
        deleteRowAction.backgroundColor = [UIColor blueColor];
        
        UIContextualAction *RowAction1 = [UIContextualAction contextualActionWithStyle:  UIContextualActionStyleNormal title:@"关注" handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) {
            //[self.titleArr removeObjectAtIndex:indexPath.row];
            completionHandler (YES);
        }];
       RowAction1.image = [UIImage imageNamed:@"icon_del"];
        RowAction1.backgroundColor = [UIColor greenColor];
    
        UISwipeActionsConfiguration *config = [UISwipeActionsConfiguration configurationWithActions:@[deleteRowAction,RowAction1]];
        return config;
        }
    

    七、iPhone X适配
    iPhone X 和 iPhone 8 的宽度一致,在垂直方向上多了145pt,状态栏不再是20而是44,没有了 Home 键,iPhone X 的底部预留给系统功能的一个区域 - Home Indicator,这部分的高度是34pt。首先看以下代码感受下:

    • 一、简单感受适配
        UILabel *lable=[[UILabel   alloc]init];
        lable.backgroundColor=[UIColor redColor];
        [self.view addSubview:lable];
        lable.text=@"12344444444";
        lable.textAlignment=NSTextAlignmentCenter;
        lable.frame=CGRectMake(0, 20, self.view.frame.size.width, 30);
    

    iphone8的运行效果:


    B567F8E0-F918-4D64-A9C2-2B1A725E3CEA.png

    iphone X的运行效果:

    6BBDDAB2-5CE3-4368-992E-79DF59B69E0C.png

    很明显iPhone X的y值不能写死20了,我们也需要考虑下44高度状态栏的iphone X了,下面像这样简单适配下就好了:

    1. frame的方式
    // UIScreen width.
    #define  ScreenWidth   [UIScreen mainScreen].bounds.size.width
    
    // UIScreen height.
    #define  ScreenHeight  [UIScreen mainScreen].bounds.size.height
    
    // iPhone X
    #define  iPhoneX (ScreenWidth == 375.f && ScreenHeight == 812.f ? YES : NO)
    
    // Status bar height.
    #define  StatusBarHeight      (iPhoneX ? 44.f : 20.f)
    
    @interface ViewController ()
    @end
    @implementation ViewController
    - (void)viewDidLoad {
        [super viewDidLoad];
        UILabel *lable=[[UILabel   alloc]init];
        lable.backgroundColor=[UIColor redColor];
        [self.view addSubview:lable];
        lable.text=@"12344444444";
        lable.textAlignment=NSTextAlignmentCenter;
        lable.frame=CGRectMake(0, StatusBarHeight , self.view.frame.size.width, 30);
        NSLog(@"%f",[UIScreen mainScreen].bounds.size.height);
    }
    
    1. Autolayout的方式
      Autolayout 视图的 top 和 bottom 一般参照的是 Top Layout Guide 和 Bottom Layout Guide. iOS11 废弃了改用安全区域(SafeArea)做参考来做适配.
    适配前的代码:
        [lable mas_makeConstraints:^(MASConstraintMaker *make) {         
          make.left.right.equalTo(self.view);
          make.height.equalTo(@30);
          make.top.equalTo(self.view).offset(20);
        }];
    适配后的代码:
       [lable mas_makeConstraints:^(MASConstraintMaker *make) {
            //以安全区域的顶部为参考作约束
     make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop);
            //哈哈,运行下就不用判断是20还是44了
       
            make.left.right.equalTo(self.view);
            make.height.equalTo(@30);
        }];
    

    3.注意iphoneX底部系统功能区域34的高度不要被控件遮挡了:
    例如你这样

       self.view.backgroundColor=[UIColor redColor];
        UILabel *lable=[[UILabel   alloc]init];
        lable.backgroundColor=[UIColor greenColor];
        [self.view addSubview:lable];
        lable.text=@"12344444444";
        lable.textAlignment=NSTextAlignmentCenter;
        lable.frame=CGRectMake(0,ScreenHeight-30, self.view.frame.size.width, 30);
    
    974D1DF1-0220-44D0-ADE6-5FCAB4FBF894.png

    因此适配就还需要个宏了。
    适配如下:

    #import "ViewController.h"
    // UIScreen width.
    #define  ScreenWidth   [UIScreen mainScreen].bounds.size.width
    
    // UIScreen height.
    #define  ScreenHeight  [UIScreen mainScreen].bounds.size.height
    
    // iPhone X
    #define  iPhoneX (ScreenWidth == 375.f && ScreenHeight == 812.f ? YES : NO)
    
    // Status bar height.
    #define  StatusBarHeight      (iPhoneX ? 44.f : 20.f)
    
    //  safe bottom margin.
    #define  SafeBottomMargin         (iPhoneX ? 34.f : 0.f)
    @interface ViewController ()
    @end
    @implementation ViewController
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.view.backgroundColor=[UIColor redColor];
        UILabel *lable=[[UILabel   alloc]init];
        lable.backgroundColor=[UIColor greenColor];
        [self.view addSubview:lable];
        lable.text=@"12344444444";
        lable.textAlignment=NSTextAlignmentCenter;
        lable.frame=CGRectMake(0,ScreenHeight-30-SafeBottomMargin, self.view.frame.size.width, 30);
    }
    

    或者你这样(哈哈,我就喜欢这样)

    #import "ViewController.h"
    #import "Masonry.h"
    @interface ViewController ()
    @end
    @implementation ViewController
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.view.backgroundColor=[UIColor redColor];
        UILabel *lable=[[UILabel   alloc]init];
        lable.backgroundColor=[UIColor greenColor];
        [self.view addSubview:lable];
        lable.text=@"12344444444";
        lable.textAlignment=NSTextAlignmentCenter;
        [lable mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.right.equalTo(self.view);
            make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom);
            make.height.equalTo(@30);
        }];
    
    }
    
    • 二、适配
      待续................

    相关文章

      网友评论

      • 33a02bf71691://2.给滑动按钮添加背景、图片
        deleteRowAction.image = [UIImage imageNamed:@"icon_del"];
        deleteRowAction.backgroundColor = [UIColor blueColor];
        这个有没有发现 不管什么图片都变成白色的了呢?

      本文标题:IOS11适配

      本文链接:https://www.haomeiwen.com/subject/chmgextx.html