10个重要的面试问题 *

最优秀的Swift开发人员和工程师可以回答的基本问题. 在我们社区的推动下,我们鼓励专家提交问题并提供反馈.

现在就雇佣一名顶尖的Swift开发者
Toptal logo是顶级自由软件开发人员的专属网络吗, designers, finance experts, product managers, 和世界上的项目经理. 顶级公司雇佣Toptal自由职业者来完成他们最重要的项目.

Interview Questions

1.

考虑下面的代码:

var array1 = [1, 2, 3, 4, 5]
var array2 = array1
array2.append(6)
var len = array1.count

What’s the value of the len variable, and why?

View answer

The len 变量等于5,也就是说 array1 has 5 elements, whereas array2 has 6 elements:

array1 = [1, 2, 3, 4, 5]
array2 = [1, 2, 3, 4, 5, 6]

When array1 is assigned to array2, a copy of array1 实际上是创建和分配的吗.

原因是swift数组是值类型(作为结构体实现)而不是引用类型(i.e. classes). 将值类型赋值给变量时, 作为参数传递给函数或方法, or otherwise moved around, 它的副本实际上被创建、分配或传递. 注意swift字典也是作为结构体实现的值类型.

Value types in swift are:

  • structs (incl. arrays and dictionaries)
  • enumerations
  • 基本数据类型(布尔型、整数型、浮点型等).)
2.

考虑下面的代码:

let op1: Int = 1
let op2: UInt = 2
let op3: Double = 3.34
var result = op1 + op2 + op3

Where is the error and why? How can it be fixed?

View answer

Swift没有在数据类型之间定义任何隐式强制转换, 即使它们在概念上几乎相同(比如 UInt and Int).

要修复错误,而不是强制转换,需要显式转换. In the sample code, 所有表达式操作数必须转换为通用的相同类型, which in this case is Double:

var result = Double(op1) + Double(op2) + op3
3.

考虑下面的代码:

var defaults = NSUserDefaults.standardUserDefaults()
var userPref = defaults.stringForKey("userPref")!
printString(userPref)

函数printString(string: string) {
    println(string)
}

Where is the bug? What does this bug cause? 正确的解决方法是什么?

View answer

The second line uses the stringForKey method of NSUserDefaults, which returns an optional, 为了解释钥匙没找到的原因, 或者对应的值不能转换为字符串.

During its execution, 如果找到键并且对应的值是字符串, 以上代码可以正常工作. But if the key doesn’t exist, 或者对应的值不是字符串, 应用程序崩溃,出现以下错误:

致命错误:在展开可选值时意外发现nil

原因是强制展开操作符 ! 尝试强制从nil展开值是可选的吗. 强制展开操作符只应在已知可选项包含非nil值时使用.

解决方案包括在强制展开可选对象之前确保它不是nil:

let userPref = defaults.stringForKey("userPref")
if userPref != nil {
    printString(userPref!)
}

一个更好的方法是使用 optional binding:

if let userPref = defaults.stringForKey("userPref") {
    printString(userPref)
}

申请加入Toptal的发展网络

并享受可靠、稳定、远程 自由Swift开发者职位

Apply as a Freelancer
4.

The String struct doesn’t provide a count or length 属性或方法来计算其包含的字符数. Instead a global countElements() function is available. 当应用于字符串时,复杂度是多少 countElements function:

  • O(1)
  • O(n)

and why?

View answer

Swift字符串支持扩展字形集群. 存储在字符串中的每个字符是一个或多个unicode标量的序列, when combined, 生成一个人类可读的字符. 因为不同的字符需要不同数量的内存, 考虑到必须顺序访问一个极端字素簇,以确定它代表哪个字符, 不可能预先知道字符串中包含的字符数, 不遍历整个字符串. 因为这个原因,复杂的 countElements function is O(n).

5.

在Swift枚举中,两者的区别是什么 raw values and associated values?

View answer

Raw values 用于将常量(文字)值关联到枚举情况. 该值类型是枚举类型的一部分, 每个枚举情况必须指定一个唯一的原始值(不允许重复的值)。.

下面的示例显示了具有类型为的原始值的枚举 Int:

enum IntEnum : Int {
    case ONE = 1
    case TWO = 2
    case THREE = 3
}

方法将枚举值转换为原始值 rawValue property:

var enumVar: intum = intum.TWO
var rawValue: Int = enumVar.rawValue

原始值可以通过使用专用初始化器转换为enum实例:

var enumVar: IntEnum? = IntEnum(rawValue: 1)

Associated values 用于将任意数据关联到特定的枚举大小写. 每个枚举情况可以有零个或多个关联值,在情况定义中声明为元组:

enum AssociatedEnum {
    case EMPTY
    case WITH_INT(value: Int)
    case WITH_TUPLE(value: Int, text: String, data: [Float])
}

而与case相关联的类型是枚举声明的一部分, 关联的值是特定于实例的, 这意味着对于不同的枚举实例,枚举大小写可以具有不同的关联值.

6.

Swift defines the AnyObject 类型别名表示任何引用类型的实例,它在内部定义为协议.

考虑下面的代码:

var array = [AnyObject]()
struct Test {}
array.append(Test())

这段代码生成一个编译错误,错误信息如下:

类型“Test”不符合协议“AnyObject”

这个错误很明显,因为struct是一个值而不是引用类型, 因此,它不实现也不能强制转换为 AnyObject protocol.

现在考虑下面的代码:

var array = [AnyObject]()
array.append(1)
array.append(2.0)
array.append("3")
array.append([4, 5, 6])
array.append([7: "7", 8: "8"])

struct Test {}
array.append(Test())

The array 数组分别用int、double、string、Array和dictionary类型的值填充. 它们都是值类型,而不是引用类型, 在所有情况下,编译器都不会报告错误. Why?

View answer

原因是swift自动桥接:

  • number types to NSNumber
  • strings to NSString
  • arrays to NSArray
  • dictionaries to NSDictionary

哪些都是引用类型.

7.

考虑下面的代码:

class Master {
    lazy var detail: detail = detail (master: self)
    
    init() {
        println("Master init")
    }
    
    deinit {
        println("Master deinit")
    }
}

class Detail {
    var master: Master
    
    init(master: Master) {
        println("Detail init")
        self.master = master
    }
    
    deinit {
        println("Detail deinit")
    }
}

func createMaster() {
    var master: master = master ()
    var detail = master.detail
}
    
createMaster()

这个bug是什么?它是如何影响内存的? How can it be fixed?

View answer

There is a strong reference cycle between Master and Detail, with Master creating an instance of Detail 并存储对它的引用 Detail 类的实例的引用 Master creator. In both cases, references are strong, 这意味着两个实例都不会被释放, causing a memory leak.

要解决这个问题,有必要至少打破两种牢固关系中的一种, by using either the weak or unowned modifier. 这两个修饰语的区别是:

  • unowned:因此,假定引用在其生命周期中始终具有一个值, 该属性必须为非可选类型.
  • weak在某些情况下,作为结果,引用可能没有价值, 属性必须是可选类型.

在上面的代码示例中,正确的解决方案是定义 Detail the reference to Master as unowned:

class Detail {
    unowned var master: Master
    ...
}
8.

下面的代码片段会导致编译时错误:

struct IntStack {
  var items = [Int]()
  func add(x: Int) {
    items.append(x) //编译时错误.
  }
}

解释发生编译时错误的原因. How can you fix it?

View answer

Structures are value types. 默认情况下,不能从值类型的实例方法中修改其属性.

However, you can optionally allow such modification to occur by declaring the instance methods as ‘mutating’; e.g.:

struct IntStack {
  var items = [Int]()
  mutating func add(x: Int) {
    items.append(x) // All good!
  }
}
9.

Consider this code:

令d = ["john": 23, "james": 24, "vincent": 34, "louis": 29]
let x = d.sort{ $0.1 < $1.1 }.map{ $0.0 }

What is the type of x? And what is its value?

View answer

x is of type [String] and of value [“约翰”,“詹姆斯”,“路易斯”,“文森特”].

10.

考虑下面的代码:

struct Planet {
    let name: String
    let distanceFromSun: Double
}

let planets = [
    行星(名称:"水星",距离:0.387),
    行星(名称:“金星”,距离:0.722),
    行星(名称:“地球”,距离:1.0),
    行星(名称:“Mars”,距离:1.52),
    行星(名称:“木星”,距离:5.20),
    行星(名称:“土星”,距离:9.58),
    行星(名称:“天王星”,距离:19.2),
    行星(名称:“海王星”,距离:30.1)
]

let result1 = planets.map { $0.name }
let result2 = planets.reduce(0) { $0 + $1.distanceFromSun }

的类型和值是什么 result1 and result2 variables? Explain why.

View answer

result1 是包含行星名称列表的字符串数组吗 result2 双星是所有行星距离的总和吗

The map method of the Array 结构类型执行源数组到另一类型数组的转换, 谁的值是通过执行作为参数传递给数组的每个元素的闭包获得的. 在上面的代码中,闭包返回 name property, so the map 方法返回行星名称数组.

给定一个初始值和一个闭包 reduce method of the Array 结构类型返回通过将闭包递归应用于数组的每个元素而获得的单个值. 闭包接受前一步计算的值(如果是第一次迭代,则为初始值)和当前数组元素, 并且期望返回与初始值相同类型的值.

In the above code, 闭包返回前一步计算的总和, plus the value of the distanceFromSun 属性设置当前元素的属性. 最后的结果是所有行星距离的总和.

面试不仅仅是棘手的技术问题, 所以这些只是作为一个指南. 并不是每一个值得雇佣的“A”候选人都能回答所有的问题, 回答所有问题也不能保证成为A级考生. At the end of the day, 招聘仍然是一门艺术,一门科学,需要大量的工作.

Why Toptal

厌倦了面试候选人? 不知道该问什么才能让你得到一份好工作?

让Toptal为你找到最合适的人.

现在就雇佣一名顶尖的Swift开发者

我们的专属Swift开发者网络

希望找到一份Swift开发人员的工作?

让Toptal为你找到合适的工作.

Apply as a Swift Developer

工作机会从我们的网络

提出面试问题

提交的问题和答案将被审查和编辑, 并可能会或可能不会选择张贴, 由Toptal全权决定, LLC.

* All fields are required

Looking for Swift Developers?

Looking for Swift Developers? 看看Toptal的Swift开发者.

Josip Petrić

Freelance Swift Developer
CroatiaToptal的自由Swift开发人员 Since July 25, 2016

作为一个有十多年经验的软件工程师, 约瑟普对建筑的可扩展性有着敏锐的认识, maintainable, 以及用户友好的应用程序. 他选择的平台是iOS,他已经为其设计和开发了广泛的应用程序, from simple ones to complex, large-scale applications. 约瑟普是一个成熟的团队领导者和团队成员,具有模范的沟通和社交技巧.

Show More

Ryan Bradley Lons

Freelance Swift Developer
United StatesToptal的自由Swift开发人员 Since January 7, 2015

Ryan是一名高级iOS和网页开发人员,热衷于创造令人惊叹的用户界面和体验. 他在开发堆栈的任何地方工作都很舒服,并且有10多年的工作经验. He's well-spoken, 很容易沟通, quick to respond, 并且擅长为你面临的任何挑战找出最佳解决方案. 瑞安有创业的动力,也了解创业公司面临的挑战.

Show More

Josh Reynolds

Freelance Swift Developer
NetherlandsToptal的自由Swift开发人员 Since May 10, 2016

拥有超过15年的成功经验,在世界各地建立了伟大的数字产品, 乔希以同情心和榜样来领导. 他会在需要的时候与团队的其他成员一起跳进战壕,并带来清晰的战略,帮助我们安全地驾驭数字海洋的湍流. Josh选择的工具是证据,同理心,清晰而动态的沟通,以及成长的心态.

Show More

Toptal Connects the Top 3% 世界各地的自由职业人才.

Join the Toptal community.

Learn more