Swift 基础小结三
-
在 Swift 中,定义了一个空协议
Error
,可以自定义一个类型并遵循该协议,表示该类型可以用于错误处理。而后,使用throw
关键字抛出该类型实例表示出现了一个错误。 -
可以将
throws
关键字添加在参数列表后,表示一个函数可以抛出错误。func test() throws -> Int
在调用可以抛出错误的函数时,需要使用
try
关键字,表示抛出的错误可以继续被当前函数抛出,当然,当前函数必须也要被throws
修饰。可以使用
do-catch
包裹抛出错误的函数,如果抛出了错误,则通过匹配不同的条件在不同的catch
分子中进行处理,如果无法处理,可以继续向外抛出错误。 -
使用
try?
将可抛出异常的函数的结果封装为可选值,即使其返回结果已经是一个可选值,仍然会再一次封装,如果函数抛出错误,那么则返回一个为nil
的可选值。 -
使用
try!
表示可抛出错误的函数在此处调用时不可能抛出错误,否则会产生一个运行时错误。 -
当有错误抛出时,余下的代码则不会在执行,所以如果想要在当前函数添加必须执行的代码,则可以使用
defer
语句块,其中的代码会在当前作用域结束之前执行,无论函数是因为错误的抛出还是因为break
或return
等语句导致的结束。一个作用域中可以有多个defer
代码块,但是其执行顺序与普通代码的执行顺序是相反的,即从后向前执行不同的defer
代码块。 -
在 Swift 中使用
is
来判断一个实例是否是某个类型或是否遵循某个协议,而as
则可以将某个实例作为某个指定类型进行使用。如果不确定类型的转换是否成功,则可以使用as?
进行转换,如果失败了,则返回值为nil
的可选值。而使用as!
则表示转换必须成功,否则会报错。 -
在 Swift 中可以使用
Any
表示任何类型,包括函数类型、可选值类型、闭包等,而AnyObject
则表示任意类类型的实例。 -
类、结构体和枚举这些类型可以相互嵌套,只是如果在外部使用时,需要指明嵌套类型所属的外层类型。
-
使用
extension
声明的扩展,可以添加计算属性,但是不能添加存储属性,也不能为已有属性添加属性观察器,但是添加类型属性时,存储属性和计算属性均可。在扩展中可以为类添加便利构造器,但不能添加指定构造器或析构器。注意在结构体中,不会使用convenience
修饰构造函数。 -
协议同类一样可以继承其他协议,声明格式也是将要继承的协议写在
:
后并用,
分隔,另外,可以在:
后添加class
表示这个协议只能被类遵循。protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol { // 这里是类类型专属协议的定义部分 }
-
如果要使用
optional
关键字将协议中的属性或方法定义为可选择的,那么便需要使用@objc
修饰协议,而这种协议只能被Objective-C
类或同样被@objc
修饰的类遵循,其他类或结构体和枚举都不可遵循该种协议。在使用可选择的协议时,需要使用可选链来避免未实现协议而产生的错误。 -
使用
extension
扩展协议,从而在扩展中实现协议中已经声明的属性或方法,或者新增一些协议方法的实现。这样,遵循该协议的类型实例可以直接使用扩展中实现的属性或方法。但是,如果遵循该协议的类型中提供了协议中属性或方法的实现,那么则使用自己的实现。 -
通过修饰符
open
、public
、internal
、filepart
、private
来声明实体的访问级别,如果不指定,默认为internal
访问级别。 -
元组的访问级别将由元组中访问级别最严格的类型来决定,函数的访问级别根据访问级别最严格的参数类型或返回类型的访问级别来决定。如果函数的返回类型的访问级别较低,为
private
,那么此时函数的访问级别应当明确指定为fileprivate
或private
,因为能访问函数,却不能访问函数的返回值明显是不合理的,同样的,子类的访问级别不能高于父类的访问级别,因为在使用子类的实例时,却不能访问父类中的属性,显然也不是我们想要的。 -
枚举成员的访问级别和枚举类型的访问级别相同,不可以单独指定。且,枚举的原始值和关联值类型的访问级别不可以低于枚举类型的访问级别。
-
在 Swift 中同样支持位运算符:与
&
、或|
、取反~
、异或^
、左移<<
、右移>>
,对于无符号数的移位运算,移出的位丢弃,不足的位补 0 即可,称为逻辑移位。而对于有符号数,因为负数是以补码的形式存储和计算的,所以在右移时,不足的位以符号位补充,左移同逻辑位移的左移一样,此称为算术位移。 -
在 Swift 中,如果运算结果发生溢出,则会报错,可以使用
&+
、&-
、&*
溢出运算符,会自动对溢出结果进行截断处理。 -
对运算符的重载,同在类型中定义类型函数类似,只是函数名称是要重载的运算符:
+
、-
、*
、/
、+=
、==
、!=
等等,除了双目运算符,还可以定义单目运算符,但是需要使用prefix
或postfix
修饰函数,表示定义的是前缀运算符还是后缀运算符。但是,不可对赋值运算符或三目条件运算符进行重载。 -
除了重载 Swift 中的标准运算符,还可以自定义运算符。定义方式和重载运算符一样,但是需要先在全局作用域中使用
operator
进行修饰,并且指明运算符是前缀的prefix
、后缀的postfix
还是中缀的infix
。prefix operator +++ extension Int { static prefix func +++ (number: inout Int) { number = number + number } }
如上,为 Int 类型定义一个
+++
前缀运算符,表示返回自己的 2 倍。