Swift面试题小记
为什么将 Array,String,Dictionary,Set,设计为值类型
堆和栈的区别
设置成值类型,能够更好的保证线程安全
理解Swift中的写时复制
Copy on write
- 在OC语言中,想要获取多个完全一致、互不干扰的对象,可以使用mutableCopy。
1
2
复制代码NSMutableArray *arr = [NSMutableArray arrayWithObjects:@10, @8, @55, nil];
NSMutableArray *array1 = [arr mutableCopy];
- 在Swift中,值类型并没有copy相关的方法。但是提供了写时复制(Copy-On-Write)的特性。
1
2
3
4
5
复制代码let array1 = [1, 2, 3, 4]
var array2 = array1
// 断点1
array2.append(2)
// 断点2
- 断点1位置,使用 lldb 命令 fr v -R [object] 来查看对象内存结构。打印出 array1,array2 内存结构如下,我们可以看到 array1 和 array2 内存地址都是 0x0000600001e4c400,说明 array1 和 array2 此时是共享同一个实例。
- 断点2位置,此时 array2 添加了新元素,打印 array2,内存结构如下,我们可以看到 array2 内存地址已经变成了0x0000000101a1a5d0,说明此时它们不再共享同一个实例,array2 对应的值进行了拷贝
写时复制允许共享同一个内存地址,直到其中之一发生改变。这样的设计使得值类型可以被多次复制而无需耗费多余的内存,只有在变化的时候才会增加开销。因此内存的使用更加高效。
该特性只对Swift中的值类型有效(struct,enum,Int,Double,Float,String,Array,Dictionary,Set),当然你也可以在自定义类型中手动实现。
属性观察器
1
willset`和 `didset
- willSet 传递新值 newValue
- didSet 传递旧值 oldValue
- 在初始化器中对属性初始化时,不会触发观察器
- 属性观察器 只能用在 存储属性 ,不可用在 计算属性
可以 为 非
lazy
(即延迟存储属性)的var
存储属性 设置 属性观察器willSet
会传递新值,默认叫 newValuedidSet
会传递旧值,默认叫 oldValue
注意:
在初始化器中设置属性值不会触发 属性观察器
- 属性定义时设置初始值也不会出发 属性观察,原因是
- 属性定义时设置初始值,本质跟在 初始化器中设置值是一样的
- 属性观察器 只能用在 存储属性 ,不可用在 计算属性
Swift泛型
Swift错误捕捉
Swift协议的可选方法
一种方法是使用@objc
的方式,但是这样修饰的 protocol 就只能被 class 实现了,也就是说,对于 struct 和 enum 类型,我们是无法令它们所实现的接口中含有可选方法或者属性的。另外,实现它的 class 中的方法还必须也被标注为 @objc,或者整个类就是继承自 NSObject。这对我们写代码来说是一种很让人郁闷的限制。
1
2
3
@objc protocol OptionalProtocol {
optional func optionalMethod()
}
另一种方法(推荐)可以使用extension,给出部分默认方法的实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
protocol OptionalProtocol {
func optionalMethod() // 可选
func necessaryMethod() // 必须
func anotherOptionalMethod() // 可选
}
extension OptionalProtocol {
func optionalMethod() {
print("Implemented in extension")
}
func anotherOptionalMethod() {
print("Implemented in extension")
}
}
class MyClass: OptionalProtocol {
func necessaryMethod() {
print("Implemented in Class3")
}
func optionalMethod() {
print("Implemented in Class3")
}
}
OC和Swift协议的区别
相同点,两者都是用作代理
不同点
Swift中的 protocol 还可以对接口进行抽象,可以实现面向协议,从而大大提高编程效率
Swift中的 protocol 可以用于值类型,结构体,枚举;
参考文章
本文由作者按照 CC BY 4.0 进行授权