iOS11,iPhoneX适配,Xcode9遇到的问题以及解决方案探讨

以下问题是自己在升级Xcode9后,在iOS11设备运行项目后遇到的问题,在此记录,说不定你也到过类似的问题,我们可以一起探讨,解决问题。

自定义导航栏高度无效

使用Xcode9和Xcode8运行同样一份代码,Xcode8中运行到iOS11系统的手机上导航栏高度是自定义的高度,而Xcode9运行高度就成了系统的44pt的高度了;目前还没有找到有效的解决方案;之前iOS11beta5版本苹果给修复了这个bug,正式系统发布后又出现了这个问题;

区别如下:

自定义UINavigationBar代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public let customNavigationBarHeight: CGFloat = isPad ? 75 : 60

final class CustomNavigationBar: UINavigationBar {

override func sizeThatFits(_ size: CGSize) -> CGSize {
return CGSize(width: UIScreen.main.bounds.width, height: customNavigationBarHeight)
}

override func layoutSubviews() {
super.layoutSubviews()

for subview in subviews {
subview.center.y = frame.height / 2
}
}

override func titleVerticalPositionAdjustment(for barMetrics: UIBarMetrics) -> CGFloat {
return -(frame.height - 44)/2
}
}

在stackeroverflow曾经搜索到一个解决方案的确能够在iOS11设备上修改导航栏高度,但是存在两个问题:第一导航栏标题栏不垂直居中;第二导航控制器的rootviewcontroller如果是tableVeiwController或者有tableView的topInset还是44pt,没有相应的跟着导航栏的高度下移:
重写layoutSubviews()的方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
override func layoutSubviews() {
super.layoutSubviews()

backgroundColor = .black
frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: customNavigationBarHeight)
for subview in self.subviews {
printLog(subview)
let stringFromClass = NSStringFromClass(subview.classForCoder)
if stringFromClass.contains("BarBackground") {
subview.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: customNavigationBarHeight)
subview.backgroundColor = .blue//self.backgroundColor
} else if stringFromClass.contains("BarContent") {
subview.frame = CGRect(x: subview.frame.origin.x, y: 0, width: subview.frame.width, height: customNavigationBarHeight)
subview.backgroundColor = .red//self.backgroundColor
subview.center.y = customNavigationBarHeight / 2
} else {
subview.center.y = frame.height / 2
}
}
}

效果和分析图如下:


这个问题还有待进一步探讨解决方案,如果哪位有解决方案,我们可以一起探讨下!

使用Xcode9打包上传构建版本时,收到警告,意思是缺少1024x1024px的Icon图片

解决方案:在项目Assets.xcassets的AppIcon中添加一张要求尺寸的Icon图片;
邮件内容如下

1
2
3
4
5
6
7
8
9
10
11
Dear developer,

We have discovered one or more issues with your recent delivery for "励步云学习". Your delivery was successful, but you may wish to correct the following issues in your next delivery:

Missing Marketing Icon - iOS Apps must include a 1024x1024px Marketing Icon in PNG format. Apps that do not include the Marketing Icon cannot be submitted for App Review or Beta App Review.

After you’ve corrected the issues, you can use Xcode or Application Loader to upload a new binary to iTunes Connect.

Regards,

The App Store team

1024x1024尺寸的Icon
同时记得叫UI添加iPhone X的LaunchImage。

swift版本不匹配的问题

如果我们项目中使用的一些依赖库是使用swift语言构建的framework,从Xcode8升级到Xcode9后是编译不过的,提示swift Module版本不匹配的错误,此时我们只需要使用Xcode9重新编译对应的framework就能够编译通过。

添加用户隐私协议提交AppStore审核,审核时间将近一个月被拒

我们公司国庆放假前一两周提交了一个版本,解决了iOS11的一些闪退和适配问题,同时添加了用户隐私条款,结果国庆放假回来之后还在审核中,审核期间我们发了无数封加急邮件,但是一直都是的回复都是正在审核!后面经过排查很打原因是用户隐私策略的添加导致的,尽管这个用户隐私协议条款的内容是公司集团法务提供的,但是好像苹果公司还得审核你的隐私协议内容。后面果断撤回这个版本(大量用户升级iOS11系统后反馈app里面的一个播放视频模块闪退,后面锁定原因是我们建立的播放视频类类名和系统的类重名了),去除隐私条款再重新提交一个新的构建版本,再写一封加急邮件,第二天立马通过审核。几天后,同时集团的其他部门提交的包含隐私策略的版本被拒,血的教训,血的坑啊!

iOS11系统设备保存图片到系统相册闪退

解决方案:在info.plist中添加访问权限,key:NSPhotoLibraryAddUsageDescription,value:是否允许$(PRODUCT_NAME)访问你的相册?

tableView在iOS11设备两边留白

如左下图红色方框留白间隙部分,以及解决后的效果右下图:

解决方案:

1
2
3
if #available(iOS 9.0, *) {
tableView.cellLayoutMarginsFollowReadableWidth = false
}

iphoneX的适配问题

由于我们公司项目中大部分都是使用storyboard开发用autolayout进行布局,所以整个iPhoneX的布局适配只花了一天就完成。iPhoneX的适配规则我认为很简单:根据苹果建议的规则以及UI给你的效果图进行修改,比如我们这边是使用苹果官方推荐的左右留白相应的距离,在安全区域(Safe Area)内布局,安全区域外的内容就别添加点击事件。具体可以查看下这两篇文章三分钟弄懂iPhone X 设计尺寸和适配关于 iPhone X 产品汪和设计狮应该了解的事之四,看完这两篇文章你对iPhoneX也就基本了解了。
先看一组界面错乱的UI

AutoLayout布局的iPhoneX适配;

很多项目的部署版本可能是低于iOS9的,那么Safe Area Layout Guides布局就不支持,但是这并不影响在iPhoneX的自动适配。刚升级到Xcode9时报的一个storyboard的错误就是Safe Area Layout Guides before iOS 9.0,应为这个选项默认是打开的,我们只需将其关闭就行。第一、像tableView,collectionView这种集合视图,autolayout已经给我们自动适配好了,我们不需要做过多的修改。如上图,左右下三边的白色部分就是自动适配好了距离,我只需将这部分颜色改为tableview的深色就适配好了。第二、上图顶部黄色区域内的左右两边距离还得添加view.safeAreaInsets左右两边的距离,这部分的适配只需将约束引出一个IBOutlet,然后在viewDidLayoutSubviews方法中重新设置,具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
@IBOutlet weak var backBtnLeadingCons: NSLayoutConstraint!
@IBOutlet weak var stageViewTrailingCons: NSLayoutConstraint!
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if #available(iOS 11.0, *) {
let inset = view.safeAreaInsets
printLog(inset)
backBtnLeadingCons.constant = inset.left + 20
stageViewTrailingCons.constant = inset.right + 10
}
}

修改后的效果图:
iPhoneX的适配效果图
还有一点要注意的是:使用Auto Layout的距离底部约束的区别,
勾选第一个是下图左边的布局,勾选下面一个是下图右边与底部挨着对齐的布局。

具体选哪种这个得更具产品要求设置即可,我这里选择第二种,与底部对齐,因为底部并没有与用户交互的事件,这样做更加符合审美。

代码约束(如Masonry)或者手写控件frame适配iPhoneX

这种情况的就需要单独针对iPhoneX写一套约束或者控件的frame。此时我们可以在定义一个全局常量(以swift为例):

1
2
3
4
// 屏幕宽高
let kScreenWidth = UIScreen.main.bounds.size.width
let kScreenHeight = UIScreen.main.bounds.size.height
let isiPhoneX = (max(kScreenWidth, kScreenHeight) == 812 && min(kScreenWidth, kScreenHeight) == 375)

  • 暂时遇到的问题就这么多,以后遇到坑在添加,同时欢迎大家添加遇到的坑!