说明:首先感谢各位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的值就行了。
五、关于自定义返回按钮
- 替换系统返回按钮图片并隐藏返回按钮文字
+(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了,下面像这样简单适配下就好了:
- 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);
}
- 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);
}];
}
- 二、适配
待续................
网友评论
deleteRowAction.image = [UIImage imageNamed:@"icon_del"];
deleteRowAction.backgroundColor = [UIColor blueColor];
这个有没有发现 不管什么图片都变成白色的了呢?