版本記錄
| 版本號(hào) | 時(shí)間 |
|---|---|
| V1.0 | 2019.04.23 星期二 |
前言
Swift作為一門開發(fā)語言,它到目前為止也四歲了,接下來這個(gè)專題主要收集一下Swift面試相關(guān)的問題。
開始
首先看下寫作環(huán)境
Swift 5, iOS 12, Xcode 10
Swift只有四年的時(shí)間,但它已經(jīng)成為iOS開發(fā)的默認(rèn)語言。隨著Swift逐漸發(fā)展到5.0版本,它變成了一種復(fù)雜而強(qiáng)大的語言,包含面向?qū)ο蠛秃瘮?shù)范例。每個(gè)版本都帶來了更多的演變和變化
但你真的有多了解Swift語音?在本文中,您將找到一些示例Swift面試問題。
您可以使用這些問題來對(duì)候選人進(jìn)行面試,以測(cè)試他們的Swift知識(shí)?;蛘吣憧梢宰约簻y(cè)試一下!如果您不知道答案,請(qǐng)不要擔(dān)心:每個(gè)問題都有一個(gè)解決方案,您可以學(xué)習(xí)。
您會(huì)發(fā)現(xiàn)問題分為三個(gè)級(jí)別:
- Beginner - 初學(xué)者:適合Swift初學(xué)者。你已經(jīng)閱讀了一兩本關(guān)于這個(gè)主題的書,并且在你自己的應(yīng)用程序中使用過Swift。
- Intermediate - 中級(jí):適合對(duì)語言有濃厚興趣的人士。您已經(jīng)閱讀了很多關(guān)于Swift并進(jìn)一步嘗試的內(nèi)容。
- Advanced - 高級(jí):適合最有經(jīng)驗(yàn)的開發(fā)人員 - 喜歡徹底探索語言和使用尖端技術(shù)的人。
在每個(gè)級(jí)別,您都會(huì)發(fā)現(xiàn)兩種類型的問題:
- Written questions - 書面問題:適用于電子郵件編程測(cè)試,因?yàn)檫@些測(cè)試可能涉及編寫代碼。
- Verbal questions - 口頭問題:通過電話或面對(duì)面交談很好,因?yàn)槟臐撛诳蛻艨梢钥陬^回答。
當(dāng)您解決這些問題和答案時(shí),請(qǐng)保持playground開放,以便在回答之前可以針對(duì)問題進(jìn)行代碼測(cè)試。我們測(cè)試了針對(duì)Xcode 10.2和Swift 5的所有答案。
Beginner Written Questions
1. Question #1
考慮下面問題
struct Tutorial {
var difficulty: Int = 1
}
var tutorial1 = Tutorial()
var tutorial2 = tutorial1
tutorial2.difficulty = 2
tutorial1.difficulty和tutorial2.difficulty的值是什么? 如果Tutorial是一個(gè)類,這會(huì)有什么不同嗎? 為什么或者為什么不?
tutorial1.difficulty是1,而tutorial2.difficulty是2。
Swift中的結(jié)構(gòu)是值類型。 您可以按值而不是引用來復(fù)制值類型。 以下代碼創(chuàng)建tutorial1的副本并將其分配給tutorial2:var tutorial2 = tutorial1更改
tutorial2不會(huì)反映到tutorial 1中。如果
Tutorial是一個(gè)類,那么tutorial1.difficulty和tutorial2.difficulty都是2。Swift中的類是引用類型。 當(dāng)你更改tutorial1的屬性時(shí),你會(huì)看到它反映在tutorial2中,反之亦然。
2. Question #2
您已使用var聲明了view1,并且已使用let聲明了view2。 有什么區(qū)別,最后一行會(huì)編譯嗎?
import UIKit
var view1 = UIView()
view1.alpha = 0.5
let view2 = UIView()
view2.alpha = 0.5 // Will this line compile?
是的,最后一行將編譯。
view1是一個(gè)變量,您可以將其重新分配給UIView的新實(shí)例。 使用let,您只能分配一次值,因此以下代碼無法編譯:view2 = view1 // Error: view2 is immutable但是,
UIView是一個(gè)帶引用語義的類,所以你可以改變view2的屬性 - 這意味著最后一行將編譯:let view2 = UIView() view2.alpha = 0.5 // Yes!
3. Question #3
這個(gè)復(fù)雜的代碼按字母順序?qū)σ唤M名稱進(jìn)行排序。 盡可能簡(jiǎn)化closure。
var animals = ["fish", "cat", "chicken", "dog"]
animals.sort { (one: String, two: String) -> Bool in
return one < two
}
print(animals)
類型推斷系統(tǒng)自動(dòng)計(jì)算閉包中的參數(shù)類型和返回類型,因此您可以刪除它們:
animals.sort { (one, two) in return one < two }您可以用
$ i表示法替換參數(shù)名稱:animals.sort { return $0 < $1 }在單個(gè)語句閉包中,您可以省略
return關(guān)鍵字。 最后一個(gè)語句的值成為閉包的返回值:animals.sort { $0 < $1 }最后,由于
Swift知道數(shù)組的元素符合Equatable,你可以簡(jiǎn)單地寫:animals.sort(by: <)
4. Question #4
此代碼創(chuàng)建兩個(gè)類:Address和Person。 然后它創(chuàng)建兩個(gè)Person實(shí)例來表示Ray和Brian。
class Address {
var fullAddress: String
var city: String
init(fullAddress: String, city: String) {
self.fullAddress = fullAddress
self.city = city
}
}
class Person {
var name: String
var address: Address
init(name: String, address: Address) {
self.name = name
self.address = address
}
}
var headquarters = Address(fullAddress: "123 Tutorial Street", city: "Appletown")
var ray = Person(name: "Ray", address: headquarters)
var brian = Person(name: "Brian", address: headquarters)
假設(shè)Brian搬到了街對(duì)面的新建筑物,你會(huì)想要像這樣更新他的記錄:
brian.address.fullAddress = "148 Tutorial Street"
這編譯并運(yùn)行沒有錯(cuò)誤。 如果您現(xiàn)在查看Ray的地址,他也會(huì)搬到新大樓。
print (ray.address.fullAddress)
這里發(fā)生了什么? 你怎么解決這個(gè)問題?
Address是一個(gè)類,并且具有引用語義,因此無論您是通過ray還是brian訪問,headquarters都是相同的實(shí)例。 更改headquarters地址將改變它們。 你能想象如果Brian收到Ray的郵件會(huì)怎么樣,反之亦然?解決方案是創(chuàng)建一個(gè)新的
Address以分配給Brian,或者將Address聲明為結(jié)構(gòu)體而不是類。
你很好,您將如何處理更多關(guān)于理論和實(shí)踐的開放式問題?
要回答其中一些問題,您可能需要在playground上玩代碼。
Beginner Verbal Questions
1. Question #1
什么是可選項(xiàng)以及可選項(xiàng)解決哪些問題?
一個(gè)可選項(xiàng)允許任何類型的變量表示缺少值。 在
Objective-C中,缺省值僅在使用nil特殊值的引用類型中可用。 值類型(如int或float)不具備此功能。Swift通過選項(xiàng)將缺少值概念擴(kuò)展到參考和值類型。 可選變量可以包含值或nil,表示缺少值。
2. Question #2
總結(jié)結(jié)構(gòu)和類之間的主要區(qū)別。
您可以將差異總結(jié)為:
- 類支持繼承,結(jié)構(gòu)體沒有。
- 類是引用類型,結(jié)構(gòu)體是值類型。
3. Question #3
什么是泛型(generics),他們解決了哪些問題?
在Swift中,您可以在函數(shù)和數(shù)據(jù)類型中使用泛型,例如 在類,結(jié)構(gòu)或枚舉中。
泛型解決了代碼重復(fù)的問題。 當(dāng)你有一個(gè)采用一種類型參數(shù)的方法時(shí),通常會(huì)復(fù)制它以適應(yīng)不同類型的參數(shù)。
例如,在下面的代碼中,第二個(gè)函數(shù)是第一個(gè)函數(shù)的“克隆”,除了它接受字符串而不是整數(shù)。
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通過采用泛型,您可以將兩個(gè)函數(shù)合二為一,同時(shí)保持類型安全。 這是泛型的實(shí)現(xiàn):
func areTheyEqual<T: Equatable>(_ x: T, _ y: T) -> Bool { return x == y } areTheyEqual("ray", "ray") areTheyEqual(1, 1)由于您在這種情況下測(cè)試相等性,因此將參數(shù)限制為實(shí)現(xiàn)
Equatable協(xié)議的任何類型。 此代碼實(shí)現(xiàn)了預(yù)期的結(jié)果,并防止傳遞不同類型的參數(shù)。
4. Question #4
在某些情況下,您無法避免使用隱式展開的選項(xiàng)(implicitly unwrapped optional)。 什么時(shí)候? 為什么?
使用隱式展開選項(xiàng)的最常見原因是:
1) 如果在實(shí)例化時(shí)無法初始化非nil的屬性。 一個(gè)典型的例子是
Interface Builder outlet,它總是在它的所有者owner之后初始化。 在這種特定情況下 - 假設(shè)它在Interface Builder中正確配置 - 您在使用它之前保證outlet是非nil的。
2) 解決強(qiáng)引用循環(huán)問題,即兩個(gè)實(shí)例相互引用并需要對(duì)另一個(gè)實(shí)例進(jìn)行非零引用。 在這種情況下,您將引用的一側(cè)標(biāo)記為無主,而另一側(cè)使用隱式未包裝的可選項(xiàng)。
5. Question #5
打開可選項(xiàng)(unwrap an optional)的各種方法有哪些? 他們?nèi)绾卧u(píng)價(jià)安全性?
var x : String? = "Test"
提示:有七種方法。
Forced unwrapping - 強(qiáng)制解包 — 不安全
let a: String = x!Implicitly unwrapped variable declaration - 隱式解包變量聲明 - 在許多情況下不安全
var a = x!Optional binding - 可選綁定 - 安全
if let a = x { print("x was successfully unwrapped and is = \(a)") }Optional chaining - 可選鏈 - 安全
let a = x?.countNil coalescing operator - Nil并運(yùn)算符 - 安全
let a = x ?? ""Guard statement - Guard聲明 - 安全
guard let a = x else { return }Optional pattern - 可選樣式 - 安全
if case let a? = x { print(a) }
后記
本篇主要講述了Swift面試資料的Questions 和 Answers,感興趣的給個(gè)贊或者關(guān)注~~~
