上期遗留一个问题:为什么 rethrows
一般用在参数中含有可以 throws
的方法的高阶函数中。
我们可以结合Swift的官方文档对rethrows
再做一遍回顾:
A function or method can be declared with the
rethrows
keyword to indicate that it throws an error only if one of its function parameters throws an error. These functions and methods are known as rethrowing functions and rethrowing methods. Rethrowing functions and methods must have at least one throwing function parameter.
返回rethrows
的函数要求至少有一个可抛出异常的函数式参数,而有以函数作为参数的函数就叫做高阶函数。
这期分两方面介绍Swift:特性修饰词和一些重要的Swift概念。
特性修饰词
在Swift语法中有很多@
符号,这些@
符号在Swift4之前的版本大多是兼容OC的特性,Swift4及之后则出现越来越多搭配@
符号的新特性。以@
开头的修饰词,在官网中叫Attributes
,在SwiftGG的翻译中叫特性,我并没有找到这一类被@
修饰的符号的统称,就暂且叫他们特性修饰词
吧,如果有清楚的小伙伴可以告知我。
从Swift5的发布来看(@dynamicCallable
,@State
),之后将会有更多的特性修饰词出现,在他们出来之前,我们有必要先了解下现有的一些特性修饰词以及它们的作用。
@available
@available
: 可用来标识计算属性、函数、类、协议、结构体、枚举等类型的生命周期。(依赖于特定的平台版本 或 Swift 版本)。它的后面一般跟至少两个参数,参数之间以逗号隔开。其中第一个参数是固定的,代表着平台和语言,可选值有以下这几个:
iOS
iOSApplicationExtension
macOS
macOSApplicationExtension
watchOS
watchOSApplicationExtension
tvOS
tvOSApplicationExtension
swift
可以使用*
指代支持所有这些平台。
有一个我们常用的例子,当需要关闭ScrollView
的自动调整inset
功能时:
// 指定该方法仅在iOS11及以上的系统设置
if #available(iOS 11.0, *) {
scrollView.contentInsetAdjustmentBehavior = .never
} else {
automaticallyAdjustsScrollViewInsets = false
}
复制代码
还有一种用法是放在函数、结构体、枚举、类或者协议的前面,表示当前类型仅适用于某一平台:
@available(iOS 12.0, *)
func adjustDarkMode() {
/* code */
}
@available(iOS 12.0, *)
struct DarkModeConfig {
/* code */
}
@available(iOS 12.0, *)
protocol DarkModeTheme {
/* code */
}
复制代码
版本和平台的限定可以写多个:
@available(OSX 10.15, iOS 13, tvOS 13, watchOS 6, *)
public func applying(_ difference: CollectionDifference<Element>) -> ArraySlice<Element>?
复制代码
注意:作为条件语句的available
前面是#
,作为标记位时是@
刚才说了,available后面参数至少要有两个,后面的可选参数这些:
deprecated
:从指定平台标记为过期,可以指定版本号
obsoleted=版本号
:从指定平台某个版本开始废弃(注意弃用的区别,deprecated
是还可以继续使用,只不过是不推荐了,obsoleted
是调用就会编译错误)该声明message=信息内容
:给出一些附加信息unavailable
:指定平台上是无效的renamed=新名字
:重命名声明
我们看几个例子,这个是Array里flatMap
的函数说明:
@available(swift, deprecated: 4.1, renamed: "compactMap(_:)", message: "Please use compactMap(_:) for the case where closure returns an optional value")
public func flatMap<ElementOfResult>(_ transform: (Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult]
复制代码
它的含义是针对swift语言,该方式在swift4.1版本之后标记为过期,对应该函数的新名字为compactMap(_:)
,如果我们在4.1之上的版本使用该函数会收到编译器的警告,即⚠️Please use compactMap(_:) for the case where closure returns an optional value
。
在Realm库里,有一个销毁NotificationToken
的方法,被标记为unavailable
:
extension RLMNotificationToken {
@available(*, unavailable, renamed: "invalidate()")
@nonobjc public func stop() { fatalError() }
}
复制代码
标记为unavailable
就不会被编译器联想到。这个主要是为升级用户的迁移做准备,从可用stop()
的版本升上了,会红色报错,提示该方法不可用。因为有renamed
,编译器会推荐你用invalidate()
,点击fix
就直接切换了。所以这两个标记参数常一起出现。
@discardableResult
带返回的函数如果没有处理返回值会被编译器警告⚠️。但有时我们就是不需要返回值的,这个时候我们可以让编译器忽略警告,就是在方法名前用@discardableResult
声明一下。可以参考Alamofire中request
的写法:
@discardableResult
public func request(
_ url: URLConvertible,
method: HTTPMethod = .get,
parameters: Parameters? = nil,
encoding: ParameterEncoding =