10个重要的面试问题 *

Toptal sourced essential questions that the best Swift developers and engineers can answer. Driven from our community, we encourage experts to submit questions and offer feedback.

现在就雇佣一名顶尖的Swift开发者
Toptal logois an exclusive network of the top freelance software developers, designers, finance experts, product managers, 和世界上的项目经理. Top companies hire Toptal freelancers for their most important projects.

Interview Questions

1.

Consider the following code:

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 实际上是创建和分配的吗.

The reason is that swift arrays are value types (implemented as structs) and not reference types (i.e. classes). 将值类型赋值给变量时, 作为参数传递给函数或方法, or otherwise moved around, 它的副本实际上被创建、分配或传递. Note that swift dictionaries are also value types, implemented as structs.

Value types in swift are:

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

Consider the following code:

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).

To fix the error, rather than casting, an explicit conversion is required. In the sample code, all expression operands must be converted to a common same type, which in this case is Double:

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

Consider the following code:

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, 为了解释钥匙没找到的原因, or for the corresponding value not being convertible to a string.

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

fatal error: unexpectedly found nil while unwrapping an Optional value

原因是强制展开操作符 ! 尝试强制从nil展开值是可选的吗. The forced unwrapping operator should be used only when an optional is known to contain a non-nil value.

The solution consists of making sure that the optional is not nil before force-unwrapping it:

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 property or method to count the number of characters it contains. Instead a global countElements() function is available. 当应用于字符串时,复杂度是多少 countElements function:

  • O(1)
  • O(n)

and why?

View answer

Swift字符串支持扩展字形集群. Each character stored in a string is a sequence of one or more unicode scalars that, when combined, 生成一个人类可读的字符. Since different characters can require different amounts of memory, and considering that an extreme grapheme cluster must be accessed sequentially in order to determine which character it represents, it’s not possible to know the number of characters contained in a string upfront, 不遍历整个字符串. 因为这个原因,复杂的 countElements function is O(n).

5.

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

View answer

Raw values 用于将常量(文字)值关联到枚举情况. 该值类型是枚举类型的一部分, and each enum case must specify a unique raw value (duplicate values are not allowed).

下面的示例显示了具有类型为的原始值的枚举 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

A raw value can be converted to an enum instance by using a dedicated initializer:

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

Associated values 用于将任意数据关联到特定的枚举大小写. Each enum case can have zero or more associated values, declared as a tuple in the case definition:

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

Whereas the type(s) associated to a case are part of the enum declaration, 关联的值是特定于实例的, meaning that an enum case can have different associated values for different enum instances.

6.

Swift defines the AnyObject type alias to represent instances of any reference type, and it’s internally defined as a protocol.

Consider the following code:

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

This code generates a compilation error, with the following error message:

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

The failure is obvious because a struct is a value and not a reference type, 因此,它不实现也不能强制转换为 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 array is filled in with values of type respectively int, double, string, array and dictionary. 它们都是值类型,而不是引用类型, 在所有情况下,编译器都不会报告错误. Why?

View answer

原因是swift自动桥接:

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

哪些都是引用类型.

7.

Consider the following code:

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, which means that none of the 2 instances will ever be deallocated, causing a memory leak.

To solve the problem it’s necessary to break at least one of the 2 strong relationships, by using either the weak or unowned modifier. 这两个修饰语的区别是:

  • unowned: the reference is assumed to always have a value during its lifetime - as a consequence, 该属性必须为非可选类型.
  • weak: at some point it’s possible for the reference to have no value - as a consequence, 属性必须是可选类型.

In the above code example, the proper solution is to define in 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. By default, the properties of a value type cannot be modified from within its instance methods.

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.

Consider the following code:

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 is an array of strings, containing the list of the planet names result2 is a double, calculated as the sum of the distance of all planets

The map method of the Array struct type performs a transformation of the source array into an array of another type, whose values are obtained by executing the closure passed as parameter to each element of the array. 在上面的代码中,闭包返回 name property, so the map 方法返回行星名称数组.

给定一个初始值和一个闭包 reduce method of the Array struct type returns a single value obtained by recursively applying the closure to each element of the array. The closure takes the value calculated at the previous step (or the initial value if it’s the first iteration) and the current array element, and is expected to return a value of the same type of the initial value.

在上面的代码中,闭包返回 sum of what calculated at the previous step, plus the value of the distanceFromSun 属性设置当前元素的属性. 最后的结果是所有行星距离的总和.

面试不仅仅是棘手的技术问题, 所以这些只是作为一个指南. Not every “A” candidate worth hiring will be able to answer them all, 回答所有问题也不能保证成为A级考生. At the end of the day, 招聘仍然是一门艺术,一门科学,需要大量的工作.

Why Toptal

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

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

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

我们的专属Swift开发者网络

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

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

Apply as a Swift Developer

工作机会从我们的网络

提出面试问题

Submitted questions and answers are subject to review and editing, 并可能会或可能不会选择张贴, 由Toptal全权决定, LLC.

* All fields are required

寻找Swift开发者?

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

Josip Petrić

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

作为一个有十多年经验的软件工程师, 约瑟普对建筑的可扩展性有着敏锐的认识, maintainable, 以及用户友好的应用程序. His platform of choice is iOS for which he has designed and developed a wide range of applications, from simple ones to complex, large-scale applications. Josip is a proven team leader and a team player with exemplary communication and social skills.

Show More

Ryan Bradley Lons

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

Ryan is a senior-level iOS and web developer passionate about creating amazing user interfaces and experiences. He's very comfortable working anywhere in the development stack and has 10+ years of doing it. He's well-spoken, 很容易沟通, quick to respond, and excels at figuring out optimal solutions for any challenge you present. Ryan has an entrepreneurial drive and understands the challenges startups face.

Show More

Josh Reynolds

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

With 15+ years of success building great digital products around the world, 乔希以同情心和榜样来领导. He will jump in the trenches with the rest of the team whenever needed and bring clear strategy to help us steer safely through the turbulent waters of the digital sea. Josh's tools of choice are evidence, empathy, clear and dynamic communication, and a growth mindset.

Show More

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

Join the Toptal community.

Learn more