文章

Swift面试题小记

为什么将 Array,String,Dictionary,Set,设计为值类型

堆和栈的区别

设置成值类型,能够更好的保证线程安全

理解Swift中的写时复制

Copy on write

  1. 在OC语言中,想要获取多个完全一致、互不干扰的对象,可以使用mutableCopy。
1
2
复制代码NSMutableArray *arr = [NSMutableArray arrayWithObjects:@10, @8, @55, nil];
NSMutableArray *array1 = [arr mutableCopy];
  1. 在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 会传递新值,默认叫 newValue
  • didSet 会传递旧值,默认叫 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 可以用于值类型,结构体,枚举;

参考文章

iOS Swift开发面试题总结

本文由作者按照 CC BY 4.0 进行授权