1.class 和 struct 的區(qū)別?
- swift中,class是引用類型,struct是值類型。值類型在傳遞和賦值時(shí)將進(jìn)行復(fù)制,而引用類型則只會(huì)使用引用對(duì)象的一個(gè)"指向"。所以他們兩者之間的區(qū)別就是兩個(gè)類型的區(qū)別。
- class有這幾個(gè)功能struct沒(méi)有的:
1.class可以繼承,這樣子類可以使用父類的特性和方法
2.類型轉(zhuǎn)換可以在runtime的時(shí)候檢查和解釋一個(gè)實(shí)例的類型
3.可以用deinit來(lái)釋放資源
4.一個(gè)類可以被多次引用- struct也有這樣幾個(gè)優(yōu)勢(shì):
1.結(jié)構(gòu)較小,適用于復(fù)制操作,相比于一個(gè)class的實(shí)例被多次引用更加安全。
2.無(wú)須擔(dān)心內(nèi)存memory leak或者多線程沖突問(wèn)題- 補(bǔ)充:
C語(yǔ)言中,struct與的class的區(qū)別:
struct只是作為一種復(fù)雜數(shù)據(jù)類型定義,不能用于面向?qū)ο缶幊獭?br> C++中,struct和class的區(qū)別:
對(duì)于成員訪問(wèn)權(quán)限以及繼承方式,class中默認(rèn)的是private的,而struct中則是public的。class還可以用于表示模板類型,struct則不行。
2.介紹一下觀察者模式
觀察者模式(Observer Pattern):定義對(duì)象間的一種一對(duì)多依賴關(guān)系,使得每當(dāng)一個(gè)對(duì)象狀態(tài)發(fā)生改變時(shí),其相關(guān)依賴對(duì)象皆得到通知并被自動(dòng)更新。
- 觀察者Observer,通過(guò)NSNotificationCenter的addObserver:selector:name:object接口來(lái)注冊(cè)對(duì)某一類型通知感興趣。在注冊(cè)時(shí)候一定要注意,NSNotificationCenter不會(huì)對(duì)觀察者進(jìn)行引用計(jì)數(shù)+1的操作,我們?cè)诔绦蛑嗅尫庞^察者的時(shí)候,一定要去報(bào)從center中將其注銷了。
- 通知中心NSNotificationCenter,通知的樞紐。
- 被觀察的對(duì)象,通過(guò)postNotificationName:object:userInfo:發(fā)送某一類型通知,廣播改變。
- 通知對(duì)象NSNotification,當(dāng)有通知來(lái)的時(shí)候,Center會(huì)調(diào)用觀察者注冊(cè)的接口來(lái)廣播通知,同時(shí)傳遞存儲(chǔ)著更改內(nèi)容的NSNotification對(duì)象。
3.在一個(gè)HTTPS連接的網(wǎng)站里,輸入賬號(hào)密碼點(diǎn)擊登錄后,到服務(wù)器返回這個(gè)請(qǐng)求前,中間經(jīng)歷了什么?

- 客戶端打包請(qǐng)求。包括url,端口啊,你的賬號(hào)密碼等等。賬號(hào)密碼登陸應(yīng)該用的是Post方式,所以相關(guān)的用戶信息會(huì)被加載到body里面。這個(gè)請(qǐng)求應(yīng)該包含三個(gè)方面:網(wǎng)絡(luò)地址,協(xié)議,資源路徑。注意,這里是HTTPS,就是HTTP + SSL / TLS,在HTTP上又加了一層處理加密信息的模塊(相當(dāng)于是個(gè)鎖)。這個(gè)過(guò)程相當(dāng)于是客戶端請(qǐng)求鑰匙。
- 服務(wù)器接受請(qǐng)求。一般客戶端的請(qǐng)求會(huì)先發(fā)送到DNS服務(wù)器。 DNS服務(wù)器負(fù)責(zé)將你的網(wǎng)絡(luò)地址解析成IP地址,這個(gè)IP地址對(duì)應(yīng)網(wǎng)上一臺(tái)機(jī)器。這其中可能發(fā)生Hosts Hijack和ISP failure的問(wèn)題。過(guò)了DNS這一關(guān),信息就到了服務(wù)器端,此時(shí)客戶端會(huì)和服務(wù)器的端口之間建立一個(gè)socket連接,socket一般都是以file descriptor的方式解析請(qǐng)求。這個(gè)過(guò)程相當(dāng)于是服務(wù)器端分析是否要向客戶端發(fā)送鑰匙模板。
- 服務(wù)器端返回?cái)?shù)字證書(shū)。服務(wù)器端會(huì)有一套數(shù)字證書(shū)(相當(dāng)于是個(gè)鑰匙模板),這個(gè)證書(shū)會(huì)先發(fā)送給客戶端。這個(gè)過(guò)程相當(dāng)于是服務(wù)器端向客戶端發(fā)送鑰匙模板。
- 客戶端生成加密信息。根據(jù)收到的數(shù)字證書(shū)(鑰匙模板),客戶端會(huì)生成鑰匙,并把內(nèi)容鎖上,此時(shí)信息已經(jīng)加密。這個(gè)過(guò)程相當(dāng)于客戶端生成鑰匙并鎖上請(qǐng)求。
- 客戶端發(fā)送加密信息。服務(wù)器端會(huì)收到由自己發(fā)送出去的數(shù)字證書(shū)加鎖的信息。 這個(gè)時(shí)候生成的鑰匙也一并被發(fā)送到服務(wù)器端。這個(gè)過(guò)程是相當(dāng)于客戶端發(fā)送請(qǐng)求。
- 服務(wù)器端解鎖加密信息。服務(wù)器端收到加密信息后,會(huì)根據(jù)得到的鑰匙進(jìn)行解密,并把要返回的數(shù)據(jù)進(jìn)行對(duì)稱加密。這個(gè)過(guò)程相當(dāng)于服務(wù)器端解鎖請(qǐng)求、生成、加鎖回應(yīng)信息。
- 服務(wù)器端向客戶端返回信息??蛻舳藭?huì)收到相應(yīng)的加密信息。這個(gè)過(guò)程相當(dāng)于服務(wù)器端向客戶端發(fā)送回應(yīng)。
- 客戶端解鎖返回信息??蛻舳藭?huì)用剛剛生成的鑰匙進(jìn)行解密,將內(nèi)容顯示在瀏覽器上。
HTTPS加密過(guò)程詳解請(qǐng)去:https原理:證書(shū)傳遞、驗(yàn)證和數(shù)據(jù)加密、解密過(guò)程解析
4.在一個(gè)app中間有一個(gè)button,在你手觸摸屏幕點(diǎn)擊后,到這個(gè)button收到點(diǎn)擊事件,中間發(fā)生了什么?
- 響應(yīng)鏈大概有以下幾個(gè)步驟:
- 設(shè)備將touch到的UITouch和UIEvent對(duì)象打包, 放到當(dāng)前活動(dòng)的Application的事件隊(duì)列中
- 單例的UIApplication會(huì)從事件隊(duì)列中取出觸摸事件并傳遞給單例UIWindow
- UIWindow使用hitTest:withEvent:方法查找touch操作的所在的視圖view
- RunLoop這邊我大概講一下
- 主線程的RunLoop被喚醒
- 通知Observer,處理Timer和Source 0
- Springboard接受touch event之后轉(zhuǎn)給App進(jìn)程中
- RunLoop處理Source 1,Source1 就會(huì)觸發(fā)回調(diào),并調(diào)用_UIApplicationHandleEventQueue() 進(jìn)行應(yīng)用內(nèi)部的分發(fā)。
- RunLoop處理完畢進(jìn)入睡眠,此前會(huì)釋放舊的autorelease pool并新建一個(gè)autorelease pool
深挖請(qǐng)去深入理解RunLoop
5. 不通過(guò)繼承,代碼復(fù)用(共享)的方式有哪些?
在swift 文件里直接寫(xiě)方法,相當(dāng)于一個(gè)全局函數(shù)。
extension 給類直接擴(kuò)展方法。
6. Set 獨(dú)有的方法有哪些?
- 不會(huì)出現(xiàn)重復(fù)的值。
- 里面的元素必須時(shí)相同的類型。
7. 實(shí)現(xiàn)一個(gè) min 函數(shù),返回兩個(gè)元素較小的元素?
func min<T : Comparable>(_ a : T , b : T) -> T {
return a < b ? a : b
}
8. map、filter、reduce 的作用?
- map : 映射 , 將一個(gè)元素根據(jù)某個(gè)函數(shù) 映射 成另一個(gè)元素(可以是同類型,也可以是不同類型)
- filter : 過(guò)濾 , 將一個(gè)元素傳入閉包中,如果返回的是false , 就過(guò)濾掉
- reduce :先映射后融合(這樣說(shuō)容易理解) , 將數(shù)組中的所有元素映射融合在一起。舉個(gè)例子:
struct Person {
let name : String
let money : String
}
let a = Person(name: "小王", money: "5.0")
let b = Person(name: "小李", money: "7.1")
let c = Person(name: "小張", money: "3.22")
let sumMoney = [a , b , c].reduce(0) {
return $0 + ($1.money as NSString).doubleValue
}
print(sumMoney)
9.map 與 flatmap 的區(qū)別
map不能將元素映射成可選類型,flatmap可以
10.如何獲取當(dāng)前代碼的函數(shù)名和行號(hào)?
函數(shù)名#functio 行號(hào)#line 文件名#file
11.如何聲明一個(gè)只能被類 conform 的 protocol?
protocol OnlyClassProtocol : class {
}
12.guard 使用場(chǎng)景?
可以理解為攔截,凡是不滿足 guard 后面條件的,都不會(huì)再執(zhí)行下面的代碼。
我一般用來(lái)解包 。 不能解包的, 就不能執(zhí)行下面的代碼
相當(dāng)于
if !(...) {
return
}
13. defer 使用場(chǎng)景?
在一對(duì)花括號(hào) : { } 里 使用defer ,這個(gè)defer 里面的內(nèi)容將會(huì)在結(jié)束 {} 前(or 后?) 被執(zhí)行
image.png
14.String 與 NSString 的關(guān)系與區(qū)別?
能夠互相轉(zhuǎn)換,一個(gè)值類型,一個(gè)引用類型
15.怎么獲取一個(gè) String 的長(zhǎng)度?
print( "abcdefg".characters.count )
//7
("abcdefg" as NSString).length //這個(gè)要算作NSString的獲取長(zhǎng)度的方法
16.throws 和 rethrows 的用法與作用?
- throws 聲明在函數(shù)的末尾,表示這個(gè)函數(shù)會(huì)拋出 Error的子類.
- rethrows 再傳入throws的閉包時(shí),這個(gè)函數(shù)返回用rethrows
17. try? 和 try!是什么意思?
- try! 強(qiáng)制拋出錯(cuò)誤,有錯(cuò)誤就會(huì)崩潰
- try? 拋出錯(cuò)誤,沒(méi)錯(cuò)誤不會(huì)崩潰直接返回
try
如果不用do catch , 就會(huì)編譯報(bào)錯(cuò)
image.png
如果函數(shù)后面加上 throws , 將錯(cuò)誤傳遞下去. 即使不用都do catch 編譯也不會(huì)報(bào)錯(cuò)。 但是調(diào)用throwfun2()還是要使用do catch
image.png
17.associatedtype 的作用?
相當(dāng)于protocol的范型
protocol Animal {
associatedtype AnimalType : Comparable
}
extension Animal {
typealias AnimalType = Self
}
18. 什么時(shí)候使用 final?
- 不允許class 被繼承
- 不允許函數(shù)被重寫(xiě)
19. private、fileprivate、internal、public和open的區(qū)別的區(qū)別?
在Swift語(yǔ)言中,訪問(wèn)修飾符有五種,分別為fileprivate,private,internal,public和open,其中 fileprivate和open是Swift 3新添加的。由于過(guò)去 Swift對(duì)于訪問(wèn)權(quán)限的控制是基于文件的,不是基于類的。這樣會(huì)有問(wèn)題,所以Swift 3新增了兩個(gè)修飾符對(duì)原來(lái)的private、public進(jìn)行細(xì)分。
private
- private所修飾的屬性或者方法只能在當(dāng)前類里訪問(wèn)
- private所修飾類只能在當(dāng)前.swift文件里訪問(wèn)
fileprivate- fileprivate訪問(wèn)級(jí)別所修飾的屬性或者方法在當(dāng)前的Swift源文件里可以訪問(wèn)。
internal(默認(rèn)訪問(wèn)級(jí)別,internal修飾符可寫(xiě)可不寫(xiě))- internal訪問(wèn)級(jí)別所修飾的屬性或方法在源代碼所在的整個(gè)模塊都可以訪問(wèn)、被繼承、被重寫(xiě)
- 如果是框架或者庫(kù)代碼,則在整個(gè)框架內(nèi)部都可以訪問(wèn),框架由外部代碼所引用時(shí),則不可以訪問(wèn)。
即使使用import,也會(huì)提示錯(cuò)誤:No such module '...'public
- 可以被任何人訪問(wèn)。但其他module中不可以被override和繼承,而在module內(nèi)可以被override和繼承。
open- 可以被任何人使用,包括override和繼承。
- 訪問(wèn)權(quán)限排序從高到低排序:open>public>interal > fileprivate >private
20.聲明一個(gè)只有一個(gè)參數(shù)沒(méi)有返回值閉包的別名?
typealias NoReturn = (String) -> Void
21.dynamic 的作用?
由于 swift 是一個(gè)靜態(tài)語(yǔ)言, 所以沒(méi)有 Objective-C 中的消息發(fā)送這些動(dòng)態(tài)機(jī)制, dynamic 的作用就是讓 swift 代碼也能有 Objective-C 中的動(dòng)態(tài)機(jī)制, 常用的地方就是 KVO 了, 如果要監(jiān)控一個(gè)屬性, 則必須要標(biāo)記為 dynamic
22.什么時(shí)候使用 @objc?
- @objc 用途是為了在 Objective-C 和 Swift 混編的時(shí)候, 能夠正常調(diào)用 Swift 代碼. 可以用于修飾類, 協(xié)議, 方法, 屬性.
- 常用的地方是在定義 delegate 協(xié)議中, 會(huì)將協(xié)議中的部分方法聲明為可選方法, 需要用到@objc
23.Optional(可選型) 是用什么實(shí)現(xiàn)的?
- Optional 是一個(gè)泛型枚舉
大致定義如下:enum Optional<Wrapped> { case none case some(Wrapped) }
- 除了使用 let someValue: Int? = nil 之外, 還可以使用let optional1: Optional<Int> = nil 來(lái)定義
24.如何自定義下標(biāo)獲取?
實(shí)現(xiàn) subscript 即可, 如
image.png
索引除了數(shù)字之外, 其他類型也是可以的
24.?? 的作用
當(dāng) ?? 前面的值為nil 的時(shí)候就取 ??后面的值
25. lazy 的作用?
只有屬性被調(diào)用的時(shí)候才會(huì)執(zhí)行l(wèi)azy
26. 一個(gè)類型表示選項(xiàng),可以同時(shí)表示有幾個(gè)選項(xiàng)選中(類似 UIViewAnimationOptions ),用什么類型表示?
繼承了OptionSet的struct , enum 。 class 沒(méi)有試過(guò),應(yīng)該也可以
27. inout 的作用?
改變函數(shù)外的值
28. Error 如果要兼容 NSError 需要做什么操作?
- Error是一個(gè)協(xié)議, swift中的Error 都是enum, 可以轉(zhuǎn) NSError
- 如果需要Error有NSError的功能,實(shí)現(xiàn) LocalizedError CustomNSError 協(xié)議
29. 下面的代碼都用了哪些語(yǔ)法糖 [1, 2, 3].map{ $0 * 2 }?
- 用$0 捕獲第一個(gè)參數(shù)。
- 只有一行代碼的時(shí)候, 隱藏掉了 return 。
30.什么是高階函數(shù)?
一個(gè)函數(shù)如果可以以某一個(gè)函數(shù)作為參數(shù), 或者是返回值, 那么這個(gè)函數(shù)就稱之為高階函數(shù), 如map、flatMap、filter、reduce?
30.如何解決引用循環(huán)?
- 轉(zhuǎn)換為值類型, 只有類會(huì)存在引用循環(huán), 所以如果能不用類, 是可以解引用循環(huán)的,
- delegate 使用 weak 屬性.
- 閉包中, 對(duì)有可能發(fā)生循環(huán)引用的對(duì)象, 使用 weak 或者 unowned, 修飾
31.定義靜態(tài)方法時(shí)關(guān)鍵字 static 和 class 有什么區(qū)別?
static 定義的方法不可以被子類繼承, class 則可以
struct 只能用static
class 的屬性只能用 static , 其他地方都能隨便用。
非class類型 一般 統(tǒng)一用 static 例如 枚舉 結(jié)構(gòu)體
protocol中 使用 static ,實(shí)現(xiàn)協(xié)議的 枚舉 結(jié)構(gòu)體 用 static
32.一個(gè) Sequence 的索引是不是一定從 0 開(kāi)始?
不是。
ArraySlice是Sequence的子類,ArraySlice就不是
33.autoclosure 的作用?
自動(dòng)閉包,將參數(shù)自動(dòng)封裝為閉包參數(shù)
34.編譯選項(xiàng) whole module optmization 優(yōu)化了什么?
編譯器可以跨文件優(yōu)化編譯代碼, 不局限于一個(gè)文件.
35.dynamic framework 和 static framework 的區(qū)別是什么?
靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù), 靜態(tài)庫(kù)是每一個(gè)程序單獨(dú)打包一份, 而動(dòng)態(tài)庫(kù)則是多個(gè)程序之間共享
36.如何讓自定義對(duì)象支持字面量初始化?
ExpressibleByArrayLiteral 可以由數(shù)組形式初始化
ExpressibleByDictionaryLiteral 可以由字典形式初始化
ExpressibleByNilLiteral 可以由nil 值初始化
ExpressibleByIntegerLiteral 可以由整數(shù)值初始化
ExpressibleByFloatLiteral 可以由浮點(diǎn)數(shù)初始化
ExpressibleByBooleanLiteral 可以由布爾值初始化
ExpressibleByUnicodeScalarLiteral
ExpressibleByExtendedGraphemeClusterLiteral
ExpressibleByStringLiteral
這三種都是由字符串初始化, 上面兩種包含有 Unicode 字符和特殊字符
一.卓同學(xué)的 Swift 面試題
答 《卓同學(xué)的 Swift 面試題》
答《卓同學(xué)的 Swift 面試題》上
答《卓同學(xué)的 Swift 面試題》下



