初级

问题1- Swift 1.0 or later

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

答案:optional类型被用来表示任何类型的变量都可以表示缺少值。在Objective-C中,引用类型的变量是可以缺少值得,并且使用nil作为缺少值。基本的数据类型如int 或者float没有这种功能。

Swift用optional扩展了在基本数据类型和引用类型中缺少值的概念。一个optional类型的变量,在任何时候都可以保存一个值或者为nil。

问题2- Swift 1.0 or later

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

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

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

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

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

并没有通用的规则决定结构体和类哪一个更好用。一般的建议是使用最小的工具来完成你的目标,但是有一个好的经验是多使用结构体,除非你用了继承和引用语义。

想要了解更多,点击这里

注意:在运行时,结构体的在性能方面更优于类,原因是结构体的方法调用是静态绑定,而类的方法调用是动态实现的。这就是尽可能得使用结构体代替类的又一个好的原因。

问题3- Swift 1.0 or later

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

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

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

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

1
2
3
4
5
6
7
8
9
10
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

Objective-C开发人员可能想到用NSObject类来解决这个问题,代码如下:

1
2
3
4
5
6
7
8
import Foundation
  
func areTheyEqual(x: NSObject, _ y: NSObject) -> Bool {
  return x == y
}
  
areTheyEqual("ray""ray"// true
areTheyEqual(1, 1) // true

这个代码会按照预期的方式工作,但是它在编译时不安全。它允许字符串和整数相比较,像这样:

1
areTheyEqual(1, "ray")

应用程序不会崩溃,但是允许字符串和整数相比较可能不是预想的结果。

通过采用泛型,可以合并这两个函数为一个并同时保持类型安全。下面是代码实现:

1
2
3
4
5
6
func areTheyEqual(x: T, _ y: T) -> Bool {
  return x == y
}
  
areTheyEqual("ray""ray")
areTheyEqual(1, 1)

上面的例子是测试两个参数是否相等,这两个参数的类型受到约束都必须遵循Equatable协议。上面的代码达到预想的结果,并且防止了传递不同类型的参数。

问题4- Swift 1.0 or later

哪些情况下你不得不使用隐式拆包?说明原因。

答案:对optional变量使用隐式拆包最常见的原因如下:

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

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

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

问题5- Swift 1.0 or later

对一个optional变量拆包有多少种方法?并在安全方面进行评价。

答案:

  • 强制拆包 !操作符——不安全

  • 隐式拆包变量声明——大多数情况下不安全

  • 可选绑定——安全

  • 自判断链接(optional chaining)——安全

  • nil coalescing 运算符(空值合并运算符)——安全

  • Swift 2.0 的新特性 guard 语句——安全

  • Swift 2.0 的新特性optional pattern(可选模式) ——安全(@Kametrixom支持)

中级

问题1- Swift 1.0 or later

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

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

  • 封装

  • 继承

  • 多态

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

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

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

问题2- Swift 1.0 or later

下面的功能特性都包含在Swift中吗?

1、泛型类

2、泛型结构体

3、泛型协议

答案:

  • Swift 包含1和2特性。泛型可以在类、结构体、枚举、全局函数或者方法中使用。

  • 3是通过typealias部分实现的。typealias不是一个泛型类型,它只是一个占位符的名字。它通常是作为关联类型被引用,只有协议被一个类型引用的时候它才被定义。

问题3- Swift 1.0 or later

在Objective-C中,一个常量可以这样定义:

1
const int number = 0;

类似的Swift是这样定义的:

1
let number = 0

两者之间有什么不同吗?如果有,请说明原因。

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

问题4- Swift 1.0 or later

声明一个静态属性或者函数,我们常常使用值类型的static修饰符。下面就是一个结构体的例子:

1
2
3
struct Sun {
  static func illuminate() {}
}

对类来说,使用static 或者class修饰符,都是可以的。它们使用后的效果是一样的,但是本质上是不同的。能解释一下为什么不同吗?

答案:

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

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

例如,在下面的代码中,当你尝试重写illuminate()函数时,编译器就会报错:

1
2
3
4
5
6
7
8
9
10
11
12
13
class Star {
  class func spin() {}
  static func illuminate() {}
}
  
class Sun : Star {
  override class func spin() {
    super.spin()
  }
  override static func illuminate() { // error: class method overrides a 'final' class method
    super.illuminate()
  }
}

问题5- Swift 1.0 or later

你能通过extension(扩展)保存一个属性吗?请解释一下原因。

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

高级

问题1- Swift 1.2

在Swift1.2版本中,你能解释一下用泛型来声明枚举的问题吗?拿下面代码中Either枚举来举例说明吧,它有两个泛型类型的参数T和V,参数T在关联值类型为left情况下使用,参数V在关联值为rihgt情况下使用,代码如下:

1
2
3
4
enum Either{
  case Left(T)
  case Right(V)
}

提示:验证上面的条件,需要在Xcode工程里面,而不是在Playgroud中。同时注意,这个问题跟Swift1.2相关,所以Xcode的版本必须是6.4以上。

答案:上面的代码会出现编译错误:

1
unimplemented IR generation feature non-fixed multi-payload enum layout

问题是T的内存大小不能确定前期,因为它依赖于T类型本身,但enum情况下需要一个固定大小的有效载荷。

最常用的解决方法是讲泛类型用引用类型包装起来,通常称为box,代码如下:

1
2
3
4
5
6
7
8
9
10
11
class Box{
  let value: T
  init(_ value: T) {
    self.value = value
  }
}
  
enum Either{
  case Left(Box)
  case Right(Box)
}

这个问题在Swift1.0及之后的版本出现,但是Swift2.0的时候,被解决了。

问题2- Swift 1.0 or later

闭包是引用类型吗?

答案:闭包是引用类型。如果一个闭包被分配给一个变量,这个变量复制给另一个变量,那么他们引用的是同一个闭包,他们的捕捉列表也会被复制。

问题3- Swift 1.0 or later

UInt类型是用来存储无符号整型的。下面的代码实现了一个有符号整型转换的初始化方法:

init(_ value: Int)

然而,在下面的代码中,当你给一个负值的时候,它会产生一个编译时错误:

let myNegative = UInt(-1)

我们知道负数的内部结构是使用二进制补码的正数,在保持这个负数内存地址不变的情况下,如何把一个负整数转换成一个无符号的整数?

答案:使用下面的初始化方法:

UInt(bitPattern: Int)

问题4- Swift 1.0 or later

描述一种在Swift中出现循环引用的情况,并说明怎么解决。

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

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

问题5- Swift 2.0 or later

Swift2.0 增加了一个新的关键字来实现递归枚举。下面的例子是一个枚举类型,它在Node条件下有两个相关联的值类型T和List:

1
2
3
enum List{
    case Node(T, List)
}

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

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

1
2
3
enum List{
    indirect case Cons(T, List)
}

Where To Go From Here?

恭喜你到了文章的最后,如果你不知道所有问题的答案,也不要感到沮丧。

因为上面中得有些问题还是比较复杂的,并且Swift是一门富有表现力的语言,还有很多需要我们学。此外,苹果公司一直改善Swift的新特性,所以即使学的最好的人也不可能知道所有的一切。

【面试必备】Swift 面试题及其答案的更多相关文章

  1. 面试(4)-spring-Spring面试题和答案

    1:69道Spring面试题和答案 转自:http://ifeve.com/spring-interview-questions-and-answers/ 目录 Spring 概述 依赖注入 Spri ...

  2. Python/Java程序员面试必备常用问题解析与答案

    转自AI算法联盟,理解python技术问题,以及一些常见的java面试中经常遇到的问题,这些面试问题分为四类: 是什么(what) 如何做(how) 说区别/谈优势(difference) 实践操作( ...

  3. 史上最全 40 道 Dubbo 面试题及答案,看完碾压面试官!

    想往高处走,怎么能不懂 Dubbo? Dubbo是国内最出名的分布式服务框架,也是 Java 程序员必备的必会的框架之一.Dubbo 更是中高级面试过程中经常会问的技术,无论你是否用过,你都必须熟悉. ...

  4. 金九银十跳槽高峰,面试必备之 Redis + MongoDB 常问80道面试题

    前言 有着“金九银十”之称的招聘旺季已经开启,跳槽高峰期也如约而至. 本文为主要是 Redis + MongoDB 知识点的攻略,希望能帮助到大家. 内容较多,大家准备好耐心和瓜子矿泉水. Redis ...

  5. 李洪强iOS经典面试题156 - Runtime详解(面试必备)

    李洪强iOS经典面试题156 - Runtime详解(面试必备)   一.runtime简介 RunTime简称运行时.OC就是运行时机制,也就是在运行时候的一些机制,其中最主要的是消息机制. 对于C ...

  6. 李洪强iOS经典面试题155 - const,static,extern详解(面试必备)

    李洪强iOS经典面试题155 - const,static,extern详解(面试必备) 一.const与宏的区别(面试题): const简介:之前常用的字符串常量,一般是抽成宏,但是苹果不推荐我们抽 ...

  7. 【面试必备】常见Java面试题大综合

    一.Java基础 1.Arrays.sort实现原理和Collections.sort实现原理答:Collections.sort方法底层会调用Arrays.sort方法,底层实现都是TimeSort ...

  8. Android&Java面试题大全—金九银十面试必备

    声明本文由作者:Man不经心授权转载,转载请联系原文作者原文链接:https://www.jianshu.com/p/375ad14096b3, 类加载过程 Java 中类加载分为 3 个步骤:加载. ...

  9. AI面试必备/深度学习100问1-50题答案解析

    AI面试必备/深度学习100问1-50题答案解析 2018年09月04日 15:42:07 刀客123 阅读数 2020更多 分类专栏: 机器学习   转载:https://blog.csdn.net ...

随机推荐

  1. 深入理解java虚拟机(2)------垃圾收集器和内存分配策略

    GC可谓是java相较于C++语言,最大的不同点之一. 1.GC回收什么? 上一篇讲了内存的分布. 其中程序计数器栈,虚拟机栈,本地方法栈 3个区域随着线程而生,随着线程而死.这些栈的内存,可以理解为 ...

  2. Effective Java 20 Prefer class hierarchies to tagged classes

    Disadvantage of tagged classes 1. Verbose (each instance has unnecessary irrelevant fields). 2. Erro ...

  3. 深入PHP内核之ZVAL

    一.PHP的变量类型 PHP的变量类型有8种: 标准类型:布尔boolen,整型integer,浮点float,字符string 复杂类型:数组array,对象object 特殊类型:资源resour ...

  4. MYSQL界面操作系统之phpMyAdmin

    linux下: 需要PHP环境支持,安装PHP自行百度 下载linux-phpMyAdmin,并解压 php -S 127.0.0.1:8081 -t phpMyAdmin/

  5. C语言的数据类型及其对应变量

    声明,定义和初始化 声明标识符iden是告诉编译器"有这么一个变量var,具体var里是什么,你自己去看".声明只需要标识符的类型和标识符名字,C语言的任何标识符在使用前都需要声明 ...

  6. Linux 环境下如何使 Chrome 浏览器字体更漂亮

    Windows 就免谈了,本身字体渲染技术 Cleartype 以及 DirectWrite 就稀烂得一塌糊涂.Mac 下面本来字体渲染就很好,所以关键就是在 Linux 下如何使 Chrome 的字 ...

  7. iTOP-4412开发板低功耗高性能的开源硬件平台——上手评测

    iTOP-4412开发板现在比较热门的开发板,笔者近期入了一套.也推荐给初学ARM的朋友学习,4412开发板搭载三星Exynos四核处理器,配备1GB内存,4GB固态硬盘EMMC存储,兼具快速读取与超 ...

  8. SSAS CUBE TEST CASES

    经过周末两天和今天的努力,基本上完成并修复了一些bug并且集成到我的MSBIHelper项目中去,可以进行数据测试了.效果图如下: 可以帮助开发人员快速生成等值的Tsql和mdx查询,辅助测试人员快速 ...

  9. css3 animation动画技巧

    一,css3 animation动画前言 随着现在浏览器对css3的兼容性越来越好,使用css3动画来制作动画的例子也越来越广泛,也随着而来带来了许多的问题值得我们能思考.css3动画如何让物体运动更 ...

  10. JVM 类加载过程

    类从加载到虚拟机到卸载,它的整个生命周期包括:加载(Loading),验证(Validation),准备(Preparation),解析(Resolution),初始化(Initialization) ...