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开发者Interview Questions
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?
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
- 基本数据类型(布尔型、整数型、浮点型等).)
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?
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
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? 正确的解决方法是什么?
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开发者职位
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?
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)
.
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.
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?
原因是swift自动桥接:
- number types to
NSNumber
- strings to
NSString
- arrays to
NSArray
- dictionaries to
NSDictionary
哪些都是引用类型.
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?
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
...
}
下面的代码片段会导致编译时错误:
struct IntStack {
var items = [Int]()
func add(x: Int) {
items.append(x) //编译时错误.
}
}
解释发生编译时错误的原因. How can you fix it?
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!
}
}
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?
x
is of type [String]
and of value [“约翰”,“詹姆斯”,“路易斯”,“文森特”]
.
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.
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
提出面试问题
Submitted questions and answers are subject to review and editing, 并可能会或可能不会选择张贴, 由Toptal全权决定, LLC.
寻找Swift开发者?
Looking for Swift Developers? 看看Toptal的Swift开发者.
Josip Petrić
作为一个有十多年经验的软件工程师, 约瑟普对建筑的可扩展性有着敏锐的认识, 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 MoreRyan Bradley Lons
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 MoreJosh Reynolds
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 MoreToptal Connects the Top 3% 世界各地的自由职业人才.
Join the Toptal community.