Swift 面试题总结

问题

  1. 什么是 optional 类型,它是用来解决什么问题的?
  2. 在 Swfit 中,什么时候用结构体,什么时候用类?
  3. 什么是泛型?泛型是用来解决什么问题的?
  4. 哪些情况下你不得不使用隐式拆包?说明原因
  5. 对一个 optional 变量拆包有多少种方法?
  6. Swift 是面向对象编程语言还是函数式编程语言?
  7. 下面的功能特性都包含在 Swift 中吗?
  1. 泛型类
  2. 泛型结构体
  3. 泛型协议
  1. 常量定义的区别
  2. static 或者 class 修饰符
  3. 你能通过 extension (扩展)保存一个属性吗?
  4. 能解释一下用泛型来声明枚举的问题吗
  5. 闭包是引用类型吗?
  6. 如何把一个负整数转换成一个无符号的整数?
  7. 描述一种在Swift中出现循环引用的情况
  8. 什么关键字可以实现递归枚举

答案

  1. 什么是 optional 类型,它是用来解决什么问题的?

optional 类型被用来表示任何类型的变量都可以表示缺少值。在 Objective-C 中,引用类型的变量是可以缺少值,并且使用 nil 作为缺少值。基本的数据类型如 int 或者 float 没有这种功能。
Swift 用 optional 扩展了在基本数据类型和引用类型中缺少值的概念。一个 optional 类型的变量,在任何时候都可以保存一个值或者为nil。

  1. 在 Swfit 中,什么时候用结构体,什么时候用类?

一直都有这样的争论:到底是用类的做法优于用结构体,还是用结构体的做法优于类。函数式编程倾向于值类型,面向对象编程更喜欢类。

在 Swift 中,类和结构体有许多不同的特性。下面是两者不同的总结:

类支持继承,结构体不支持。

类是引用类型,结构体是值类型

并没有通用的规则决定结构体和类哪一个更好用。一般的建议是使用最小的工具来完成你的目标,但是有一个好的经验是多使用结构体,除非你用了继承和引用语义。
注意:在运行时,结构体的在性能方面更优于类,原因是结构体的方法调用是静态绑定,而类的方法调用是动态实现的。这就是尽可能得使用结构体代替类的又一个好的原

  1. 什么是泛型?泛型是用来解决什么问题的?

泛型是用来使类型和算法安全的工作的一种类型。在 Swift 中,在函数和数据结构中都可以使用泛型,例如类、结构体和枚举。

泛型一般是用来解决代码复用的问题。常见的一种情况是,你有一个函数,它带有一个参数,参数类型是
A,然而当参数类型改变成B的时候,你不得不复制这个函数。

例如,下面的代码中第二个函数就是复制第一个函数——它仅仅是用 String 类型代替了 Integer 类型。

> func areIntEqual(x: Int, _ y: Int) -> Bool {
  return x == y
}
  
func areStringsEqual(x: String, _ y: String) -> Bool {
  return x == y
}
  
areStringsEqual("ray", "ray") // true
areIntEqual(1, 1) // true
  1. 哪些情况下你不得不使用隐式拆包?说明原因

1、对象属性在初始化的时候不能 nil,否则不能被初始化。典型的例子是 Interface Builder outlet
类型的属性,它总是在它的拥有者初始化之后再初始化。在这种特定的情况下,假设它在 Interface Builder 中被正确的配置——
outlet 被使用之前,保证它不为 nil。

2、解决强引用的循环问题——当两个实例对象相互引用,并且对引用的实例对象的值要求不能为 nil 时候。在这种情况下,引用的一方可以标记为
unowned,另一方使用隐式拆包。

建议:除非必要,不要对 option
类型使用隐式拆包。使用不当会增加运行时崩溃的可能性。在某些情况下,崩溃可能是有意的行为,但有更好的方法来达到相同的结果,例如,通过使用
fatalError( ) 函数。

  1. 对一个 optional 变量拆包有多少种方法?

强制拆包 ! 操作符——不安全 隐式拆包变量声明——大多数情况下不安全 可选绑定——安全 自判断链接(optional
chaining)——安全 nil coalescing 运算符(空值合并运算符)——安全 Swift 的新特性 guard 语句——安全
Swift 的新特性 optional pattern(可选模式) ——安全(@Kametrixom支持)

  1. Swift 是面向对象编程语言还是函数式编程语言?

Swift 是一种混合编程语言,它包含这两种编程模式。它实现了面向对象的三个基本原则:

封装 继承 多态 说到 Swift
作为一种函数式编程语言,我们就不得不说一下什么是函数式编程。有很多不同的方法去定义函数式编程语言,但是他们表达的意义相同。

最常见的定义来自维基百科:…它是一种编程规范…它把电脑运算当做数学函数计算,避免状态改变和数据改变。

很难说 Swift 是一个成熟的函数式语言,但是它已经具备了函数式语言的基础。

  1. 下面的功能特性都包含在 Swift 中吗?
  1. 泛型类
  2. 泛型结构体
  3. 泛型协议 Swift 包含 1 和 2 特性。 泛型可以在类、结构体、枚举、全局函数或者方法中使用。 3 是通过 typealias 部分实现的。 typealias 不是一个泛型类型,它只是一个占位符的名字。
    它通常是作为关联类型被引用,只有协议被一个类型引用的时候它才被定义。
  1. 常量定义的区别

const 常量是一个在编译时或者编译解析时被初始化的变量。通过let创建的是一个运行时常量,是不可变得。它可以使用 stattic 或者
dynamic 关键字来初始化。谨记它的的值只能被分配一次。

  1. static 或者 class 修饰符

static 修饰的属性或者修饰的函数都不可以重写。但是使用 class 修饰符,你可以重写属性或者函数。

当 static 在类中应用的时候,static 就成为 class final 的一个别名。

  1. 你能通过 extension (扩展)保存一个属性吗?

不能。扩展可以给当前的类型添加新的行为,但是不能改变本身的类型或者本身的接口。如果你添加一个新的可存储的属性,你需要额外的内存来存储新的值。扩展并不能实现这样的任务。

  1. 能解释一下用泛型来声明枚举的问题吗

拿下面代码中 Either 枚举来举例说明吧,它有两个泛型类型的参数 T 和 V,参数 T 在关联值类型为left情况下使用,参数
V在关联值为 rihgt 情况下使用,代码如下:

enum Either{
  case Left(T)
  case Right(V)
}

答案:上面的代码会出现编译错误: unimplemented IR generation feature non-fixed
multi-payload enum layout

问题是 T 的内存大小不能确定, 因为它依赖于T类型本身,但 enum 情况下需要一个固定大小的有效载荷。
最常用的解决方法是讲泛类型用引用类型包装起来,通常称为 box,代码如下:

class Box{
  let value: T
  init(_ value: T) {
    self.value = value
  }
}
  
enum Either{
  case Left(Box)
  case Right(Box)
}
  1. 闭包是引用类型吗?
    闭包是引用类型。如果一个闭包被分配给一个变量,这个变量复制给另一个变量,那么他们引用的是同一个闭包,他们的捕捉列表也会被复制。
  2. 如何把一个负整数转换成一个无符号的整数?
  3. 描述一种在Swift中出现循环引用的情况
    述一种在 Swift 中出现循环引用的情况,并说明怎么解决。

答案:循环引用出现在当两个实例对象相互拥有强引用关系的时候,这会造成内存泄露,原因是这两个对像都不会被释放。只要一个对象被另一个对象强引用,那么该对象就不能被释放,由于强引用的存在,每个对象都会保持对方存在。

解决这个问题的方法是,用 weak 或者 unowned 引用代替其中一个的强引用,来打破循环引用。

  1. 什么关键字可以实现递归枚举

indirect 关键值可以允许递归枚举,代码如下:

enum List{

 indirect case Cons(T, List)

}
  1. OC和Swift区别

枚举
字典
语法
swift面向函数
方法调用
static
静态语言
值类型
可选

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值