Swift 面试问题总结一

问题1

tutorial1.difficultytutorial2.difficulty 分别是什么? 如果将 Tutorial 改为 class 呢?为什么?

1
2
3
4
5
6
7
struct Tutorial {
var difficulty: Int = 1
}
var tutorial1 = Tutorial()
var tutorial2 = tutorial1
tutorial2.difficulty = 2

答:

tutorial1.difficulty 值为 1;tutorial2.difficulty 的值为 2。如果将 Tutorial 改为 class,则两者的值都为 2。因为 struct 为值类型(value type), class 为引用类型(reference type)。

问题2

下面的 view1 和 view2 有什么区别?最后一行能成功编译吗?

1
2
3
4
5
6
7
import UIKit
var view1 = UIView()
view1.alpha = 0.5
let view2 = UIView()
view2.alpha = 0.5

答:

view1 为变量,view2 为常量。即 view1 可以重新赋值一个 UIView 实例,而 view2 不可。
最后一行会成功编译,因为 UIView 是 class 。

问题3

尽你所能去简化👇的代码。

1
2
3
4
5
var animals = ["fish", "cat", "chicken", "dog"]
animals.sort { (one: String, two: String) -> Bool in
return one < two
}
print(animals)

答:

1
animals.sort(by: <)

详情参见此处

问题4

下面代码的 ray 的 address 显示是错误的,应该是 “123 Tutorial Street”。请 fix bug 。

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 Address {
var fullAddress: String
var city: String
init(fullAddress: String, city: String) {
self.fullAddress = fullAddress
self.city = city
}
}
class Person {
var name: String
var address: Address
init(name: String, address: Address) {
self.name = name
self.address = address
}
}
var headquarters = Address(fullAddress: "123 Tutorial Street", city: "Appletown")
var ray = Person(name: "Ray", address: headquarters)
var brian = Person(name: "Brian", address: headquarters)
brian.address.fullAddress = "148 Tutorial Street"
print (ray.address.fullAddress)

答:

将 Address 改为 struct 。或者重新创建一个 Address 实例赋值给 Brian 。

问题5

optional 是什么?它的底层是由什么实现的?它解决了什么问题?

答:
A type that represents either a wrapped value or nil, the absence of a value.
从官方文档可知,optional 是一种可以允许存储 nil 的类型。即如果你声明的变量值可能为空时,你可以将它声明为 optional 类型。

1
2
var name: String? = nil
name = "Swift"

它的底层是由 Enumerate 实现的。

1
2
3
4
5
6
7
// 出自:Swift 必备Tips - 多重 optional
enum Optional<T> : _Reflectable, NilLiteralConvertible {
case None
case Some(T)
//...
}

它解决了 OC 中只能对象类型才能为 nil 的问题,在 Swift 中任意类型都可以声明为 optional 类型。

问题6

struct 与 class 的区别?

答:

  • struct 为值类型,它不支持继承
  • class 为引用类型,支持继承

问题7

generics(泛型) 是什么?它解决了什么问题?

答:

泛型可以使你的代码更加灵活,使你的函数可以使用与多种类型。例如下面的函数,可以适用于将任意类型的两个变量进行交换操作。

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

它解决了不同类型相同功能的函数冗余问题。详情可参见此处

问题8

如何安全的获取 x 的值?

1
var x : String? = "Test"

答:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 使用默认值
print(x ?? "default value")
// if-let
if let value = x {
print(value)
}
// guard-let
func getUnwrapValue() {
guard let guardValue = x else { return }
print(guardValue)
}
getUnwrapValue()

问题9

nil.none 的区别?

答:

两者是等同的,没有区别。.noneOptional.none 的简写。

1
let flag = (nil == .none) // flag 为 true

nil 的使用更加普遍,它也是被推荐使用的。

问题10

下面的代码有什么问题?如何修改?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class ThermometerClass {
private(set) var temperature: Double = 0.0
public func registerTemperature(_ temperature: Double) {
self.temperature = temperature
}
}
let thermometerClass = ThermometerClass()
thermometerClass.registerTemperature(56.0)
public struct ThermometerStruct {
private(set) var temperature: Double = 0.0
public mutating func registerTemperature(_ temperature: Double) {
self.temperature = temperature
}
}
let thermometerStruct = ThermometerStruct()
thermometerStruct.registerTemperature(56.0)

答:

最后一行编译报错,因为 thermometerStruct 是常量,不允许改变。
let thermometerStruct = ThermometerStruct() 改为 var thermometerStruct = ThermometerStruct() 即可。

问题11

下面的代码将输出什么?为什么?

1
2
3
4
5
6
7
8
9
var thing = "cars"
let closure = { [thing] in
print("I love \(thing)")
}
thing = "airplanes"
closure()

答:

输出 I love cars,因为在你定义 closure 的时候,它已经获取了 thing 的拷贝值,在后面再修改 thing 的值不会影响 closure 中的值。

可以修改为下面的代码来改变该问题:

1
2
3
var colsure = {
print("I love \(thing)")
}

这种方式它会在调用 colsure 再获取 thing 的值。

问题12

if-let 和 guard-let区别?

答:

两者都用于安全解包。区别是 guard-let 必须有 else 分支,在 else 中 return。

问题13

Swift 是否支持函数重载?

答:

支持。维基百科中重载的定义:重载允许创建数项名称相同但输入输出类型或个数不同的子程序,它可以简单地称为一个单独功能可以执行多项任务的能力

1
2
3
// 函数名相同,参数名和类型不同
func testFunc(num: Int) { }
func testFunc(str: String) { }

问题14

Swift 中的 extension 是否可以定义存储属性?

答:

extension 不支持定义存储类型,只可以定义计算属性。

问题15

Swift 中的 extension 和 OC 中 category 的区别?

答:

extension 没有名字,而 category 有名字。

参考: