你的旧版本 App 为何运行在 iPhone 12 上没有异常?
背景
当我在 10月14日 iPhone 12 系列发布直播,看到 iPhone 12 系列的分辨率后,我注意到这些分辨率是全新的时,我立即在群里吐槽:又需要适配一波了。我只是以为宽高变化会导致字号变化,然而更严重的问题是我们判断是否是刘海屏使用了如下代码(这种写法是不完善的);
self.is_iphonex = (SCREEN_MAX_LENGTH812.f || SCREEN_MAX_LENGTH896.f);
是否是刘海屏是枚举所有符合预期的设备高度来判断的,它的好处是快速稳定,但遇到新机型就悲催了。在新 iPhone 12 系列中,屏幕高度分别为:
Device Retina 屏幕像素 (pt) 物理像素 (px)
iPhone 12 Pro 6.7″ 3X 926 x 428 2778 x 1284
iPhone 12 Pro 6.1″ 3X 390 x 844 2532 x 1170
iPhone 12 6.1″ 3X 390 x 844 2532 x 1170
iPhone 12 Mini 5.4″ 3X 360 x 780 2340 x 1080
iPhone 11 Pro Max 3X 414 x 896 2688 x 1242
所以如果(SCREEN_MAX_LENGTH812.f || SCREEN_MAX_LENGTH896.f) 代码来判断刘海屏,定位导航栏位置肯定是错误的。预期表现是导航栏被刘海遮住。
巡查App Store 的 App 在 iPhone 12 的表现
当我拿到 蓝色 iPhone 12 的第一件时间就是看看各个 App 在适配方便有哪些异常表现,大概看了10 几个 App,除了 斗鱼,哔哩哔哩 外大部分适配都没有大问题。有问题,我不意外,
斗鱼顶部导航适配出错
,但是其他 App ,包括我们自己的 App,全屏的界面导航都没问题。
严选 App
为什么有些 OK,有些异常?
经过实际测试,分别用 Xcode 12.0 和 Xcode 12.1 分别在真机 iPhone 12 上运行;发现 Xcode 12.1 build 的 App 真机运行是有问题的。所有目前 App Store 里运行有问题的 App,如斗鱼,是用了 Xcode 12.1 最新版本上传的 ipa。所以他们的差别在哪里?
观察到, Xcode 12.1 里已经有 iPhone 12 的模拟器,所以说用 Xcode 12.1 是认识 iPhone 12 的。回想几年前当 iPhone X 出现时,旧的 App 是如何在 iPhone X 上表现的—— App 运行在屏幕的中间,上线留有黑边。
这里需要解释下苹果 App 的向后兼容规则:
当 App 运行在自己不认识的新设备上时,系统会把新设备当做上一代的设备来使用。换言之,新设备运行 的App 在兼容模式。避免 App 去处理 build 之时,还不存在的设备上。
这个规则在用户在设置 -> 显示和亮度 -> 放大显示 里设置了放大效果时,就是如此兼容的。
iPhone 11 Pro Max 标准显示(Standard Zoom) 下分辨率是 414×896 points;而如果设置为放大显示(Display Zoom)会被当做 iPhone 11 Pro 设备,此时分辨率是 375×812 points。
运作在兼容模式,一些常见的高度,如 statusbar、 bottombar 的尺寸是有影响的。
真实 iPhone 11 Pro 的顶部安全距离是 44,底部安全距离是 34;而运行在放大显示(Display Zoom)下,虽然屏幕分辨率相同,但顶部安全距离是 40,底部安全距离是 31;
结论
因为用 Xcode 12.0 打的 ipa,在 iPhone 12 上运行在兼容模式,尺寸是 iPhone 11,重点是顶部安全距离、底部安全距离都合 iPhone 11 保持一致,所以不会有问题;而用 Xcode 12.1 打的包,运行在了全新的分辨率,如果没有适配,肯定出问题。
附录, 正确判断是否是刘海屏的方法
苹果会推荐我们使用 safeAreaInsets 来获取,从 ViewController.view 获取时,时机太迟了,需要从更早创建的地方获取如 keyWindow,如:
(CGFloat)topOffset{
if (@available(iOS 11, *)) {
return [UIApplication sharedApplication].keyWindow.safeAreaInsets.top + kNavigationbarHeight;
}return 20 + kNavigationbarHeight;
}
直接使用 topOffset 来设置顶部安全距离或者通过判断 bottomOffset 是否大于 0 来确认是否是刘海屏,进而设置不同尺寸。
如果是判断刘海屏然后再加 statusbar 高度的作法(不推荐),你还需要完整的 statusbar 高度的表;
iPhone11: 48
iPhone12/12 pro/12 pro max: 47
iPhone12 mini: 50 (工作在 iPhone 11 Pro 缩放模式)
iPad Pro、IPad Air: 24
Other iPhones: 44.
非刘海屏: 20
参考
How iOS Apps Adapt to the various iPhone 12 Screen Sizes
WWDC 2019: 224 Modernizing Your UI for iOS 13
你的旧版本 App 为何运行在 iPhone 12 上没有异常?的更多相关文章
- 旧版本APP被开发人员下架,新版本重新上传依然显示被下架
新接了一个项目,这个项目在苹果商城上面的版本已经被原来另外一家公司的开发人员下架.我们重新设计.开发.上传,申请加急审核,终于完成手动发布.但是发布成功后,新版本提示:被开发人员下架.以前虽然迭代开发 ...
- IOS如何下载旧版本应用APP
前言 文章相对来说比较复杂,特别是查找版本ID对应的步骤,这里推荐使用另一种方案,操作起来更简单. 本文介绍如何使用Workflow及Fiddler下载IOS旧版本APP应用. 实现原理 通过Work ...
- 下载历史版本App超详细教程
有些时候我们需要下载旧版本的 App 进行研究或者其他用途,然而在 iOS 下,苹果的 App Store 里面默认只能下载最新版本的 App,对滴,就是这么任性,不服不行.然而在 Android 里 ...
- 下载历史版本App
文/timhbw(简书作者)原文链接:http://www.jianshu.com/p/edfed1b1822c著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. 1.软件准备 [必备]C ...
- 青花瓷运用->下载历史版本App
1.软件准备 [必备]Charles4.0.1 下载密码: jfnk [不需要,配合Charles食用效果更佳]Paw2.3.1 下载密码: t3my 2.正式开始 2.1 打开Charles青花瓷 ...
- 混合式App开发 Apicloud 官方iPhone X 适配
iPhone X 适配 由于iPhone X的特殊造型,为了方便开发者对iPhone X进行适配,苹果在iOS 11中引入了Safe Area的概念,引擎也在api对象下添加了safeArea属性和s ...
- 利用 Charles Proxy 下载旧版本 iOS App
一.软件准备 1.旧版本 iTunes1.IPSW Downloads:https://ipsw.me/2.百度网盘链接: https://pan.baidu.com/s/1PO9Z12o-rqZ_J ...
- python3.7环境下创建app,运行Django1.11版本项目报错SyntaxError: Generator expression must be parenthesized
咳咳!!! 今天用命令行创建django项目中的app应用,出现了这样一个错误 这个错误在python3.6版本下安装运行django 1.11版本正常运行,但python3.7版本下运行django ...
- python3.7环境下创建app、运行Django1.11版本项目报错Generator expression must be parenthesized
有些同学喜欢追求新鲜感~但追求新鲜感终归是要付出一点点代价的 在编程领域有一句至理名言:用东西不要用最新的! 就像每次苹果系统的升级都会有相当一部分用户的手机成砖一样 下面我们就介绍一个因版本升级带来 ...
随机推荐
- 【5】进大厂必须掌握的面试题-Java面试-spring
spring面试问题 Q1.什么是spring? Spring本质上是一个轻量级的集成框架,可用于用Java开发企业应用程序. Q2.命名Spring框架的不同模块. 一些重要的Spring Fram ...
- 空间视频和GIS
摘要. GIS的空间数据基本单位表示通常是根据 点,线和面.但是,另一种类型的空间数据正在变得越来越频繁 捕获的是视频,但在GIS中却被很大程度上忽略了.数字录像时 是现代社会中常见的一种媒介,包含多 ...
- MeteoInfoLab脚本示例:OMI Grid HDF数据
OMI卫星格点数据的例子,全球臭氧柱总量分布.脚本程序: #Add data file folder = 'D:/Temp/hdf/' fns = 'OMI-Aura_L3-OMTO3e_2005m1 ...
- day44 Pyhton 数据库Mysql
内容回顾 什么是进程? 就是为了形容执行中的程序的一种称呼 它是操作系统中资源分配的最小单位 进程之间是数据隔离的,占用操作系统资源相对多 独立存在的 谈谈你对并发的理解 同时有多个任务需要执行,但是 ...
- JS中实现Trim(),TrimStart(),TrimEnd() 的方法
//去除字符串头尾空格或指定字符 String.prototype.Trim = function (c) { if (c == null || c == "") { var st ...
- 基于python实现单链表代码
1 """ 2 linklist.py 3 单链表的构建与功能操作 4 重点代码 5 """ 6 7 class Node: 8 " ...
- JetBrains-CLion永久激活教程
前言 JetBrains Clion 是一款专为 C/C++ 开发所设计的跨平台 IDE.本文适用 JetBrains CLion v2019.3/3.1/3.2/3.3 永久激活,附破解补丁和激活码 ...
- centos8上安装openresty
一,openresty的官网地址: http://openresty.org/ 说明:说一下openresty的安装方式: 从openresty的安装目录下,可以看到openresty编译安装了自己作 ...
- 全文检索Solr集成HanLP中文分词【转】
以前发布过HanLP的Lucene插件,后来很多人跟我说其实Solr更流行(反正我是觉得既然Solr是Lucene的子项目,那么稍微改改配置就能支持Solr),于是就抽空做了个Solr插件出来,开源在 ...
- Linux用户和组管理命令-切换用户su
切换用户或以其他用户身份执行命令 su: 即 switch user,命令可以切换用户身份,并且以指定用户的身份执行命令 格式: su [options...] [-] [user [args...] ...