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);
    }];

}
  • 二、适配
    待续................

你可能感兴趣的:(IOS11适配)