- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章IOS11新特性与兼容适配由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
ios11发布以来,很多新的特性为开发工作提供了方便,小编在此给大家介绍一下ios11的新特性以及在兼容适配等做的工作.
1. uiview变化 。
1.1. 更加方便的rtl边距设置 。
在之前的系统中我们会使用layoutmargins来获取和设置控件显示内容部分的边缘与控件边缘的距离。在ios 11中,新增directionallayoutmargins属性来指定边距。这两个属性的结构定义如下:
1
2
3
4
5
6
7
|
typedef
struct
uiedgeinsets {
cgfloat top, left, bottom, right;
} uiedgeinsets;
////
typedef
struct
nsdirectionaledgeinsets {
cgfloat top, leading, bottom, trailing;
} nsdirectionaledgeinsets
|
从结构上看主要是将uiedgeinsets结构的left和right调整为nsdirectionaledgeinsets结构的leading和trailing。这一调整主要是为了right to left(rtl)语言下可以进行自动适配,例如:要实现文本每行尾部边距设置为30px,在以前做法则需要判断语言来区分哪些是rtl语言,然后再做设置,如:
1
2
3
4
5
6
7
8
9
|
if
([uiview userinterfacelayoutdirectionforsemanticcontentattribute:self.view.semanticcontentattribute] == uiuserinterfacelayoutdirectionrighttoleft)
{
// right to left 语言下每行尾部在左边
self.view.layoutmargins.left = 30;
}
else
{
self.view.layoutmargins.right = 30;
}
|
ios 11 后则可以一步到位,如:
1
|
self.view.directionallayoutmargins = nsdirectionaledgeinsetsmake(0, 0, 0, 30);
|
注:测试时需要添加rtl本地化语言才能看到效果 。
1.2. 安全区域 。
在ios 11中新增了安全区域的概念,目的是告诉开发者在这个区域下绘制的内容的显示才是有效的,否则会存在被遮挡的情况(特别是iphonex那帅气的刘海)。在uiview中新增safearealayoutguide和safeareainsets来获取屏幕的安全区域(对于frame布局时是很有用的)。如图所示:
safearea示意图 。
举个例子,在一个空白的uiviewcontroller中,分别在viewdidload和viewdidappear方法中输出view.safeareainsets观察边距情况,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
- (
void
)viewdidload
{
[super viewdidload];
nsstring *edgestr = nsstringfromuiedgeinsets(self.view.safeareainsets);
nsstring *layoutfrmstr = nsstringfromcgrect(self.view.safearealayoutguide.layoutframe);
nslog(@
"viewdidload safeareainsets = %@, layoutframe = %@"
, edgestr, layoutfrmstr);=
}
- (
void
)viewdidappear:(
bool
)animated
{
[super viewdidappear:animated];
nsstring *edgestr = nsstringfromuiedgeinsets(self.view.safeareainsets);
nsstring *layoutfrmstr = nsstringfromcgrect(self.view.safearealayoutguide.layoutframe);
nslog(@
"viewdidappear safeareainsets = %@, layoutframe = %@"
, edgestr, layoutfrmstr);
}
|
可以看到其输出为:
1
2
|
2017-09-19 14:45:50.246095+0800 sample[5608:1365070] viewdidload safeareainsets = {0, 0, 0, 0}, layoutframe = {{0, 0}, {375, 667}}
2017-09-19 14:45:50.257807+0800 sample[5608:1365070] viewdidappear safeareainsets = {20, 0, 0, 0}, layoutframe = {{0, 20}, {375, 603}}
|
可见,在视图显示完成的时候view的顶部边距变为了20px,而这20px正是状态栏的高度。同样原理,如果你的是一个 。
uinavigationcontroller那在显示的时候view.safeareainsets就会变成{64, 0, 0, 0}。注意:在该vc下所有的uiview及其子类获取到safeareainsets的值是相同的.
如果你想准确地知道安全区域是什么时候被改变的,可以重写uiview的safeareainsetsdidchange方法,在这个方法里面可以监听安全区域的边距调整的事件(如果使用的是uiviewcontroller,其也提供相应方法来实现监听,下一章节会讲述该部分内容),代码如下:
1
2
3
4
|
- (
void
)safeareainsetsdidchange
{
//写入变更安全区域后的代码...
}
|
如果你不想让safeareainsets影响你的视图布局,则可以将insetslayoutmarginsfromsafearea设置为no,所有的视图布局将会忽略safeareainsets这个属性了。要注意的是,insetslayoutmarginsfromsafearea仅用于autolayout,即使该属性为no,视图的safeareainsets还是一样有值,而且安全区域变更方法safeareainsetsdidchange一样被调用.
2. uiviewcontroller变化 。
2.1. 废除api 。
2.1.1. automaticallyadjustsscrollviewinsets方法 。
ios 7中使用该方法来自动调整uiscrollview的contentinset。在ios 11之后将会使用uiscrollview的 。
contentinsetadjustmentbehavior属性来代替该方法.
2.1.2. toplayoutguide和bottomlayoutguide属性 。
ios 7中使用这两个属性来指导带有导航栏(naviagtionbar)和页签栏(tabbar)的视图排版。其作用如下图所示 。
toplayoutguide & bottomlayoutguide 。
在ios 11之后将使用安全区域(safe area)来代替该部分功能的实现.
2.2. 排版 。
2.2.1. additionalsafeareainsets属性 。
ios 11加入安全区域后,对于vc则可以通过该属性来对该区域附加一个边距信息。如:
1
|
self.additionalsafeareainsets = uiedgeinsetsmake(30, 0, 0, 30);
|
注意:这里是附加边距,意思就是在原有的safeareainsets值中增加对应的边距值。如果原来的是{10, 0, 0, 10}, 则最后得出的边距是{40, 0, 0, 40}.
2.2.2. systemminimumlayoutmargins和viewrespectssystemminimumlayoutmargins属性 。
该属性表示了一个系统最小的边距信息,所有的视图排版都应该遵循这个边距信息的。除非将viewrespectssystemminimumlayoutmargins设置为no.
2.2.3. viewlayoutmarginsdidchange方法 。
根视图的边距变更时会触发该方法的回调。可以通过该方法来处理当边距改变时子视图的布局.
2.2.4. viewsafeareainsetsdidchange方法 。
当视图的安全区域发生变更时会触发该方法的回调。可以通过该方法来处理安全区域变更时的子视图布局.
3. uinavigationbar变化 。
ios 11中加入了大标题模式,其显示效果如下所示:
大标题效果图 。
实现该效果需要将导航栏的preferslargetitles设置为yes,如:
self.navigationcontroller.navigationbar.preferslargetitles = yes,
4. uinavigationitem变化 。
4.1 控制大标题的显示 。
如果你想控制每个视图的大标题是否显示,这需要使用uinavigationitem的largetitledisplaymode属性来控制大标题的显示。该属性为枚举类型,定义如下:
1
2
3
4
5
6
7
8
9
|
typedef
ns_enum(nsinteger, uinavigationitemlargetitledisplaymode)
{
/// 自动模式,会继承前一个navigationitem所设置的模式
uinavigationitemlargetitledisplaymodeautomatic,
/// 当前 navigationitem 总是启用大标题模式
uinavigationitemlargetitledisplaymodealways,
/// 当前 navigationitem 总是禁用大标题模式
uinavigationitemlargetitledisplaymodenever,
}
|
根据上面的描述,可以在vc初始化init或者awakefromnib方法中设置显示图标模式:
1
|
self.navigationitem.largetitledisplaymode = uinavigationitemlargetitledisplaymodealways;
|
4.2 控制搜索控制器 。
ios 11 中新增了两个属性searchcontroller和hidessearchbarwhenscrolling。这两个属性主要用于简化vc对uisearchcontroller的集成以及视觉优化。其中searchcontroller属性用于指定当前vc的一个搜索控制器。而hidessearchbarwhenscrolling属性则用于控制当视图滚动时是否隐藏搜索栏的ui,当该值为yes时,搜索栏只有在内容视图(uiscrollview及其子类)顶部是才会显示,在滚动过程中会隐藏起来;当该值为no时,则不受滚动影响一直显示在导航栏中。具体的代码实现如下:
1
2
3
4
5
6
7
8
|
- (
void
)awakefromnib
{
[super awakefromnib];
//设置searchcontroller到navigationitem
self.searchcontroller = [[uisearchcontroller alloc] initwithsearchresultscontroller:self];
self.navigationitem.searchcontroller = self.searchcontroller;
self.navigationitem.hidessearchbarwhenscrolling = yes;
}
|
搜索栏隐藏后效果 。
5. uiscrollview变化 。
之前的系统中,如果你的滚动视图包含在一个导航控制器下,系统会自动地调整你的滚动视图的contentinset。而ios 11新增adjustedcontentinset属性取替之前contentinset的处理方式。这两者之间的关系如下图所示:
adjustedcontentinset & contentinset 。
通过一个例子来验证这说法,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
- (
void
)viewdidload
{
[super viewdidload];
nslog(@
"viewdidload"
);
nslog(@
"self.tableview.contentinset = %@"
, nsstringfromuiedgeinsets(self.tableview.contentinset));
nslog(@
"self.tableview.adjustedcontentinset = %@"
, nsstringfromuiedgeinsets(self.tableview.adjustedcontentinset));
}
- (
void
)viewdidappear:(
bool
)animated
{
[super viewdidappear:animated];
nslog(@
"viewdidappear"
);
nslog(@
"self.tableview.contentinset = %@"
, nsstringfromuiedgeinsets(self.tableview.contentinset));
nslog(@
"self.tableview.adjustedcontentinset = %@"
, nsstringfromuiedgeinsets(self.tableview.adjustedcontentinset));
}
|
执行后输出下面信息:
1
2
3
4
5
6
|
2017-09-20 11:54:09.361348+0800 sample[1276:375286] viewdidload
2017-09-20 11:54:09.361432+0800 sample[1276:375286] self.tableview.contentinset = {0, 0, 0, 0}
2017-09-20 11:54:09.361462+0800 sample[1276:375286] self.tableview.adjustedcontentinset = {0, 0, 0, 0}
2017-09-20 11:54:09.420000+0800 sample[1276:375286] viewdidappear
2017-09-20 11:54:09.420378+0800 sample[1276:375286] self.tableview.contentinset = {0, 0, 0, 0}
2017-09-20 11:54:09.420554+0800 sample[1276:375286] self.tableview.adjustedcontentinset = {20, 0, 0, 0}
|
可见,tableview的adjustedcontentinset自动改变了,但是contentinset的值是保持不变的。注:一定要是vc的根视图为uiscrollview或者其子类才能够得到adjustedcontentinset的值,否则获取到的是空值。而且非根视图的滚动视图就会被安全区域所裁剪,看到的样式如下图所示:
样式效果对比 。
通过使用contentinsetadjustmentbehavior属性可以控制 adjustedcontentinset的变化。该属性为枚举类型,其定义如下:
1
2
3
4
5
6
|
typedef
ns_enum(nsinteger, uiscrollviewcontentinsetadjustmentbehavior) {
uiscrollviewcontentinsetadjustmentautomatic,
uiscrollviewcontentinsetadjustmentscrollableaxes,
uiscrollviewcontentinsetadjustmentnever,
uiscrollviewcontentinsetadjustmentalways,
}
|
其中uiscrollviewcontentinsetadjustmentautomatic与uiscrollviewcontentinsetadjustmentscrollableaxes一样,scrollview会自动计算和适应顶部和底部的内边距并且在scrollview 不可滚动时,也会设置内边距; 。
uiscrollviewcontentinsetadjustmentnever表示不计算内边距;uiscrollviewcontentinsetadjustmentalways则根据视图的安全区域来计算内边距.
如果需要感知adjustedcontentinset的变化,然后根据变化进行不同操作则可以通过重写新增的adjustedcontentinsetdidchange方法或者实现uiscrollviewdelegate中的scrollviewdidchangeadjustedcontentinset方法来实现。如:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
//重写方法
- (
void
)adjustedcontentinsetdidchange
{
[super adjustedcontentinsetdidchange];
//执行操作...
}
//实现委托
- (
void
)scrollviewdidchangeadjustedcontentinset:(uiscrollview *)scrollview
{
//执行操作...
}
|
除了新增上述所说的边距相关属性外,还新增了contentlayoutguide和framelayoutguide属性,用于描述内容布局和整体布局信息.
6. ui主线程操作日志提醒 。
之前的系统中如果你不小心将ui放入非主线程操作时,debug日志是没有任何信息反馈的,导致有时候在排错时非常困难。在新的xcode 9中,如果你处于调试状态,将ui放入非主线程操作,如:
1
2
3
4
5
|
dispatch_async(dispatch_get_global_queue(0, 0), ^{
self.tv = [[uitableview alloc] initwithframe:self.view.bounds];
[self.view addsubview:self.tv];
nslog(@
"self.tv.adjustedcontentinset = %@"
, nsstringfromuiedgeinsets(self.tv.adjustedcontentinset));
});
|
log中会出现下面提示:
1
2
3
4
5
6
7
8
9
10
11
12
|
=================================================================
main
thread
checker: ui api called on a background
thread
: -[uiview bounds]
pid: 16919, tid: 2972321,
thread
name: (none), queue name: com.apple.root.
default
-qos, qos: 21
backtrace:
4 sample 0x00000001004885dc __29-[viewcontroller viewdidload]_block_invoke + 112
5 libdispatch.dylib 0x000000010077149c _dispatch_call_block_and_release + 24
6 libdispatch.dylib 0x000000010077145c _dispatch_client_callout + 16
7 libdispatch.dylib 0x000000010077d56c _dispatch_queue_override_invoke + 980
8 libdispatch.dylib 0x0000000100782b54 _dispatch_root_queue_drain + 616
9 libdispatch.dylib 0x0000000100782880 _dispatch_worker_thread3 + 136
10 libsystem_pthread.dylib 0x000000018300b130 _pthread_wqthread + 1268
11 libsystem_pthread.dylib 0x000000018300ac30 start_wqthread + 4
|
从日志中了解到一个main thread checker的东西,根据苹果官方文档来看他是作用在appkit(osx中)、uikit还有一些相关api上的后台线程,主要是用来监控这些框架中的接口是否在主线程中进行调用,如果没有则发出警告日志。因此,利用这个功能可以让我们快速地定位那些地方存在问题.
以上就是本次ios11新特性与兼容适配介绍的全部内容,如果大家还有任何问题可以在下方留言处留言讨论.
最后此篇关于IOS11新特性与兼容适配的文章就讲到这里了,如果你想了解更多关于IOS11新特性与兼容适配的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
目录 C#特性 1. 概括 2. 语法 定义特性类 应用特性
是否有关于 Python 语言必须提供哪些功能的文章/论文?为什么应该使用 Python 而不是任何其他语言? Python 的优点和缺点是什么? 最佳答案 Why Python和 Why Pytho
我想弄清楚为什么 .x比*.x具有更高的特异性当后者有望获胜时。 不是*.x应该具有 0-0-1-1 的特异性(1 个类,1 个标签)而 .x只是一个类(class) 0-0-1-0 ? 考虑以下基本
在尝试评估非 instanceof 条件时,我发现了我在 Groovy 2.4.7、1.6.0 JVM 中没有预料到的行为。 总之: class Foo { static Boolean
当使用可变结构和属性时,编译器可以解决一些问题,但不能对其他相当明显的事情做同样的事情,这对我来说似乎很奇怪。 以下面的自动属性为例: Vector2 Vector { get; set; } 而不是
我对 ES3 有一定的了解,但我对 ES5 的特性不是很了解。我 - 或多或少 - 知道: Object.create(), Object.freeze() “使用严格” getter 和 sette
我最近开始将 Django 1.5.4 用于带有 MySQL 后端的 Web 应用程序。就在一开始,我遇到了某些限制,这让我想知道 Django 是否是继续前进的正确方法。 一些明显的缺点是: 缺少复
在函数模板的定义中,模板参数的实例化一般是未知的。类型特征可用于在编译时获取一些信息。例如,这是 is_pointer 的一个简单应用: template void foo(T p) { cout
我正在设计页面的样式,该页面具有除最后一个框外的带底部边框的连续框。我为所有框应用类 .box 并添加 .box_last 以仅隐藏最后一个框的边框。 .box { border-bottom-s
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
我有兴趣编制一份不建议在嵌入式系统中使用的 c++ 功能列表(这可能会导致人们推荐使用 c 而不是 c++)。如果您知道,请尝试添加原因,或者将您的原因添加到其他人的答案中。 这是一个开始(我知道的唯
作为一名 Ruby 程序员,您是否曾觉得任何使用起来有点冒险的功能,可能是因为它的奇怪行为?它可能有很好的文档记录,但在调试时很难找到,或者难以记住? 我通常尽量远离 String#gsub!。文档说
我正在开发一个连接到健身 watch 的蓝牙应用程序。这是我第一次使用蓝牙。我设法使用出色的 FlutterBlue 将我的应用程序与设备连接起来图书馆。 但是我无法理解我从阅读中获得的结果。这是我阅
1. 迭代器(Iterator)的介绍 背景:指针可以用来遍历存储空间连续的数据结构,但是对于存储空间费连续的,就需要寻找一个行为类似指针的类,来对非数组的数据结构进行遍历。 定义:迭代器是一种检
嗨,伙计们,有没有动态更改 Spring 属性文件内容的好例子?如果您能给我一些示例或链接,我将不胜感激。 非常感谢 最佳答案 我想你可以使用 ReloadableResourceBundleMess
SystemVerilog 引入了一些非常有用的结构来改进编码风格。然而,正如我的一位同事经常说的,“你不是在写软件,你是在描述硬件。”考虑到这一点,当最终结果需要合成时,应该避免语言的哪些特征?这个
我定义了这些测试依赖项 / Test Dependencies lazy val wiremock = "com.github.tomakehurst" % "wir
我正在为 Android 手机和 Android watch (wearOS) 编写应用程序。这些应用程序将通过蓝牙相互通信。基本上,Android 手机上的应用程序将与 WearOS 设备绑定(bi
我正在为 Android 手机和 Android watch (wearOS) 编写应用程序。这些应用程序将通过蓝牙相互通信。基本上,Android 手机上的应用程序将与 WearOS 设备绑定(bi
我有兴趣提高我的设计能力(设计具有属性、方法等的类)。即如何决定类、方法和属性应该是什么? 你们能建议我改进这个的好 Material 吗? 最佳答案 请看: Any source of good o
我是一名优秀的程序员,十分优秀!