WWDC 2017 大会中发布了 iOS 11,在带来了一系列炫酷的框架之后,对 UIKit 也进行了一定程度的更新,这其中有几十项 API 更新或新增,让我们来看一些比较好玩的吧!
本篇只是不完全统计,但将持续更新,最完整的统计和解释请前往【Apple Developer Sites】
新增:Drag and Drop
拖与拽这个功能大家应该都不陌生,这是在移动设备上移动文件或文字最好的解决方案,比普通的粘贴复制更具表达性、易读性和便捷性,而 Apple 经过了长时间锤炼将该功能添加到 UIKit 大家族中来,让它有了无与伦比的 Multi-touch 体验,关于 Drag and Drop 更多的解释请前往我的【Drag and Drop】。
新增:Large Title
只要您安装了 iOS 11 beta,就一定会发现系统内建应用在 UI 设计上有了非常大的改变,其中最为惹人注目的就是 “大标题”,也就是 large title,它看起来就像这样:
不得不说,这确实增加了可读性,官方的解释是,这强调了用户现在正处于某个多级导航的根部,例如您现在有一个 Navigation Controller,您可以在根视图使用 large title,而如果您的 Tabbar Controller 类似于系统的时钟应用,子标签没有多级导航,那么您或许不应该使用 large title,因为这将误导用户使其以为还有某个地方可以进入下一级导航。
该功能是一系列 API 组合使用的结果,使用也很简单:
1.首先你得有一个 Navigation Controller
2.在导航控制器的根视图控制器下(例如 UITableView Controller)的 viewDidLoad 处,添加代码:
/** language: Swift 4 */
// 设置导航控制器的 navigationBar 的 largeTitle 可用
self.navigationController?.navigationBar.prefersLargeTitles = true
// 设置 largeTitle 的显示方式为自动
self.navigationItem.largeTitleDisplayMode = .automatic
// 设置标题内容
self.navigationItem.title = "Title"
现在运行您的项目,如果正常的话,您的导航栏应该就有了 large title 效果,就像这样:
如果失败了,不要灰心,请细心检查您的控制器或其它属性是否设置正确。
同时这也会让所有 Navigation Controller 的子目录均显示大标题,而如果您想(您应该)让子目录不显示大标题,需要在子目录的视图控制器下单独设置:
self.navigationItem.largeTitleDisplayMode = .never
largeTitleDisplayMode
是一个 UINavigationItem 的 LargeTitleDisplayMode 枚举变量,它有如下值:
- automatic:系统自动决定是否显示大标题,在显示与不显示之间将有很棒的动画过度,效果预览可参照 设置 应用。
- always:时刻显示大标题
- never:不显示大标题
新增:additionalSafeAreaInsets
使用这个属性可以给您的内容增加一片 “安全区”,这个安全区有点类似于视图保护,它可以保证您的 tableView、scrollView 等滑动视图中的内容不会显示在您设置的安全区内。
比如我们直接在 ViewController 里添加一个 tableView,第一行一定会和 status bar 有重合,我们不希望这样,所以我们可以:
/** file: ViewController.swift */
override func viewDidLoad() {
self.additionalSafeAreaInsets = UIEdgeInsetsMake(20, 0, 0, 0)
}
这会让 tableView 的顶部出现一片高度为 20 的空白区域。
安全区和 contentInset 的区别
安全区可以让该控制器的所有类似 tableView 的视图都适用,contentInset 虽然可以实现相同效果但必须一个一个去设置。
同时我们也有了 func viewSafeAreaInsetsDidChange()
方法,它会在安全区被改变时调用。
新增:func preferredScreenEdgesDeferringSystemGestures() -> UIRectEdge
通常,屏幕边缘的手势动作(Screen Edge Gesture)是由系统管理的,没有一个 API 能直接将这些手势拿出来编辑,但如果您想创造一个沉浸式 App 体验,例如视频、游戏等,想要防止 Control Center 或 Notification Center 直接被手势调出,同时让自己的 Gesture 优先被调用,就可以给这个方法提供一个返回值,它表示指定一处边缘让此处的自定义 Gesture 优先于系统的 Gesture:
override func preferredScreenEdgesDeferringSystemGestures() -> UIRectEdge {
return UIRectEdge.all
}
UIRectEdge
是一个结构体,它有一些属性可以被使用:
public static var top: UIRectEdge { get }
public static var left: UIRectEdge { get }
public static var bottom: UIRectEdge { get }
public static var right: UIRectEdge { get }
public static var all: UIRectEdge { get }
它们都是静态的,所以使用相对简单,现在我们来看看使用该方法的效果:
可以看到,我们已经不能直接滑动出控制中心了,而是有一个小箭头,这是什么意思大家应该都懂吧~
但是通知中心并没有类似效果,不只是 Bug 还是其它的问题,在以后的 beta 版中我会持续测试。
改动:UIViewPropertyAnimator
UIViewPropertyAnimator
是 Apple 在 iOS 10 推出的视图动画类,它可以更方便的创建属性动画,你可以自定义动画曲线来控制动画的播放速度。
在 iOS 11 中,这个类又新增了两个属性,分别是:
var scrubsLinearly: Bool
var pausesOnCompletion: Bool
scrubsLinearly
属性默认是 true,它令您的动画在被用手指拖动时(如果您的动画允许这样做的话)或其它因素影响时,当影响因素停止时,动画剩余的部分将用线型曲线去播放。而若是设置为 false,动画剩余的部分依然由指定的动画曲线播放。
过期的属性
这些属性在 iOS 11 中不建议使用或已过期:
var bottomLayoutGuide: UILayoutSupport
var topLayoutGuide: UILayoutSupport
var automaticallyAdjustsScrollViewInsets: Bool