1、如下Swift的代码的输出结果是什么?请说明理由。

1
2
3
4
var arr1 = ["1", "2", "3"]
var arr2 = arr1
arr2.append("4")
print(arr1)

答:

输出结果是:1,2,3

此处考察的是Swift和OC中数组数据类型的区别(值类型与引用类型),因为在Swift中数组是值类型,所以当值类型赋值给变量时,它会创建一个新的数组赋值给arr2。

2、如下Swift代码运行会不会报错?请说明原因,如何解决此类问题?

1
2
3
let a: Double = 4.0
let b: Int = 2
let c = a + b

答:

上面的代码会报错,因为Swift是强类型语言,Double和Int类型之间的运算需要显示转换。

解决办法有以下三种:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 方法一:显示类型转换
let c = a + Double(b)


// 方法二:自定义运算符
infix operator +: AdditionPrecedence
func +(lhs: Double, rhs: Int) -> Double {
return lhs + Double(rhs)
}


// 方法三:写个Double类型的Extension
extension Double {
func add(int: Int) -> Double {
return self + Double(int)
}
}
let c = a.add(b)

3、如下Swift代码运行会不会报错?请说明原因

1
2
3
4
5
6
7
8
struct Person {
var name: string
var sex: string
}

var arrTest: [AnyObject] = []
let person = Person()
arrTest.append(person)

答:

上述这段代码中会出现两处编译错误:

(1)结构体的属性没有初始化,解决方案有两个:

  • 添加结构体初始化方法并对name和sex属性进行初始化
  • 把name和sex属性改成可选

(2)定义的arrTest数组是AnyObject类型,在Swift中 AnyObject 只能用于引用类型,struct是值类型。

4、如下Swift代码运行会不会报错?请说明原因

1
2
3
4
5
6
7
8
9
10
11
12
13
struct Person {
var name: string
var sex: string

init(name: String, sex: String) {
self.name = name
self.sex = sex
}

func updateName(newName: String) {
self.name = newName
}
}

答:

由于在Swift中结构体是值类型,所以正常情况下值类型的属性无法直接在实例函数中进行修改,如果说确实需要这么做,Swift也给我们提供一个方式,那就是在其实例函数前面添加 mutating 关键字。

如下代码所示:

1
2
3
mutating  func updateName(newName: String) {
self.name = newName
}

5、给定Swift字典[“cat”: 1001, “dog”: 1004, “bird”: 1003, “pig”: 1002],输出[“dog”, “bird”, “pig”, “cat”],请使用Swift代码实现。

答:

1
2
3
4

let pets = ["cat": 1001, "dog": 1004, "bird": 1003, "pig": 1002]
let petTypes = pets.sorted { $0.value < $1.value }.map { $0.key}
print(petTypes)

6、如下代码的输出结果是什么?请说明原因

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
26
class SchoolInfo {
var name: String
static func == (left: SchoolInfo, right: SchoolInfo) -> Bool {
return left.name == right.name
}
init(name: String) {
self.name = name
}
}

let school1 = SchoolInfo(name: "yyys")
let school2 = SchoolInfo(name: "yyys")
let school3 = school1

if school1 == school2 {
print("one equal two 1")
}
if school1 == school3 {
print("one equal three 1")
}
if school1 === school2 {
print("one equal two 2")
}
if school1 === school3 {
print("one equal three 2")
}

答:

上述考察的是Swift中的==和===之间的区别:

  • == 用来比较值是否相等
  • === 用来比较两个引用是否指向同一个对象实例(实例是否相等)

所以最终的输出结果是:

one equal two 1

one equal three 1

one equal three 2

7、写一个函数交换变量a和b的值,变量a和变量b的数据类型不限

答:此题主要考察的是Swift中泛型的使用

1
2
3
4
5
func swapValue<T>(a: inout T, b: inout T) {
let temp = a
a = b
b = temp
}

8、如下代码能编译通过吗?请说明原因

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class SchoolInfo {
var name: String
var sex: String?
init(name: String) {
self.name = name
}
}

struct Person {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
}

let school1 = SchoolInfo(name: "xxxx")
school1.sex = "male"
let person = Person(name: "xxx", age: 22)
person.age = 23

答:

以上代码不能编译通过,此处考察的是class和struct值类型和引用类型的区别:
把person改成var,即可编译通过

9、请写出下面代码的输出结果并说明原因

1
2
3
4
5
6
7
8
9
10
11
var personx = Person(name: "personx")
let schoolx = SchoolInfo(name: "schoolx")
let block = { [schoolx, personx] in
print("the block personx name = \(personx.name)")
print("the block schoolx name = \(schoolx.name)")
}
personx.name = "persons"
schoolx.name = "schools"
block()
print("the personx name = \(personx.name)")
print("the schoolx name = \(schoolx.name)")

答:

上述代码的输出结果:

the block personx name = personx

the block schoolx name = schools

the personx name = persons

the schoolx name = schools

原因:此题考察的还是类与结构体的区别,因为block通过捕获列表 [personx] 捕获了 personx 的​​当前值的副本,所以后续在block外部修改personx则不会影响block内的副本,schoolx是class,捕获的是引用,所以能正常修改

10、如下代码是否存在问题,请说明原因

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
26
27
28
29
30
31
32

class CustomDataManager {
var didFinishLoad: (() -> Void)?
func delayUpdate(delay: Double, complete: () -> Void) {
DispatchQueue.global().asyncAfter(deadline: .now() + delay, execute: complete)
}
func loadData() {
print("the network is start loading!")
DispatchQueue.global().async {
// 模拟请求网络
Thread.sleep(forTimeInterval: 5)
print("the network is callback!")
self.didFinishLoad?()
}
}
}
class CustomVC:UIViewController {
let dataManager = CustomDataManager()
override func viewDidLoad() {
super.viewDidLoad()
self.dataManager.loadData()
self.dataManager.didFinishLoad = {
print("the start update UI!")
self.updateCustomUI()
}
self.dataManager.delayUpdate(delay: 5) {
print("delay update UI!")
self.updateCustomUI()
}
}
func updateCustomUI() {}
}

答:

上述代码存在以下2个问题:

1、delayUpdate 函数的complete逃逸闭包未标记@escaping​,导致编译错误

2、didFinishLoad闭包存在循环引用,导致CustomVC无法释放

——————————————————————————————————

完整优秀版请移步小专栏:
Swift面试题2025(附答案)

更多好文推荐,关注《iOS开发秘籍》,免费解锁完整版

本文内容中部分来自网络,后续会持续更新完善。欢迎一起学习交流!

如需转载,请注明出处

Swift面试题2025(附答案)