1.什么是函數(shù)式編程?
函數(shù)式編程其實(shí)是一種編程思想, 代碼寫出來只是它的表現(xiàn)形式
在面向?qū)ο蟮木幊趟枷胫? 我們將要解決的一個(gè)個(gè)問題, 抽象成一個(gè)個(gè)類, 通過給類定義屬性和方法, 讓類幫助我們解決需要處理的問題.(其實(shí)面向?qū)ο笠步忻钍骄幊? 就像給對(duì)象下一個(gè)個(gè)命令)
而在函數(shù)式編程中, 我們則通過函數(shù)描述我們要解決的問題, 以及解決問題需要怎樣的方案.
RxSwift
2.swift相對(duì)于OC有哪些優(yōu)點(diǎn)?
1、swift語法簡(jiǎn)單易讀、代碼更少,更加清晰、易于維護(hù)
2、更加安全,optional的使用更加考驗(yàn)程序員對(duì)代碼安全的掌控
3、泛型、結(jié)構(gòu)體、枚舉都很強(qiáng)大
4、函數(shù)為一等公民,便捷的函數(shù)式編程
5、有命名空間 基于module
6、類型判斷
oc的優(yōu)點(diǎn)、運(yùn)行時(shí)
3.什么是泛型,swift在哪些地方使用了泛型?
泛型(generic)可以使我們?cè)诔绦虼a中定義一些可變的部分,在運(yùn)行的時(shí)候指定。使用泛型可以最大限度地重用代碼、保護(hù)類型的安全以及提高性能。
例如 optional 中的 map、flatMap 、?? (泛型加逃逸閉包的方式,做三目運(yùn)算)
4.defer、guard的作用?
defer 包體中的內(nèi)容一定會(huì)在離開作用域的時(shí)候執(zhí)行
guard 過濾器,攔截器
5.swift語法糖 ?!的本質(zhì)(實(shí)現(xiàn)原理)
? 為optional的語法糖
Optional< T > 是一個(gè)包含了 nil 和 普通類型的枚舉,確保使用者在變量為nil的情況下的處理
! 為optional 強(qiáng)制解包 的語法糖
6.舉例swift中模式匹配的作用?
模式匹配: 在switch中體現(xiàn)最明顯
通配符模式: _
標(biāo)識(shí)符模式:let i = 1
值綁定模式:case .Student(let name) 或者 case let .Student(name)
元祖模式:case (let code, _)
可選模式:if case let x? = someOptional { }
類型轉(zhuǎn)換模式:case is Int: 或者 case let n as String:
表達(dá)式模式:范圍匹配 case (0..<2) case(0...2, 2...4)
條件句中使用where: case (let age) where age > 30
if case let:if case let .Student(name) = xiaoming { }
for case let: for case let x in array where x > 10 {} 或者 for x in array where x > 10
7.swift中closure與OC中block的區(qū)別?
1、closure是匿名函數(shù)、block是一個(gè)結(jié)構(gòu)體對(duì)象
2、都能捕獲變量
3、closure通過逃逸閉包來在block內(nèi)部修改變量,block 通過 __block 修飾符
8.什么是capture list,舉例說明用處?
捕獲列表
weak unowned
9.swift中private與fileprivate的區(qū)別?
private的作用域被約束與被定義的當(dāng)前類作用域,fileprivate作用域是整個(gè)文件
10.Set 獨(dú)有的方法有哪些?
intersect(_:)// 根據(jù)兩個(gè)集合中都包含的值創(chuàng)建的一個(gè)新的集合
exclusiveOr(_:) // 根據(jù)只在一個(gè)集合中但不在兩個(gè)集合中的值創(chuàng)建一個(gè)新的集合
union(_:) // 根據(jù)兩個(gè)集合的值創(chuàng)建一個(gè)新的集合
subtract(_:) //根據(jù)不在該集合中的值創(chuàng)建一個(gè)新的集合
isSubsetOf(_:) //判斷一個(gè)集合中的值是否也被包含在另外一個(gè)集合中
isSupersetOf(_:) //判斷一個(gè)集合中包含的值是否含有另一個(gè)集合中所有的值
isStrictSubsetOf(:) isStrictSupersetOf(:) //判斷一個(gè)集合是否是另外一個(gè)集合的子集合或者父集合并且和特定集合不相等
isDisjointWith(_:) //判斷兩個(gè)集合是否不含有相同的值
11.實(shí)現(xiàn)一個(gè) min 函數(shù),返回兩個(gè)元素較小的元素
func minNum<T: Comparable>(a: T, b: T) -> T {
return a > b ? a : b
}
12.map、filter、reduce 的作用
1、map 是Array類的一個(gè)方法,我們可以使用它來對(duì)數(shù)組的每個(gè)元素進(jìn)行轉(zhuǎn)換
let intArray = [1, 3, 5]
let stringArr = intArray.map {
return "\($0)"
}
// ["1", "3", "5"]
2、filter 用于選擇數(shù)組元素中滿足某種條件的元素
let filterArr = intArray.filter {
return $0 > 1
}
//[3, 5]
3、reduce 把數(shù)組元素組合計(jì)算為一個(gè)值
let result = intArray.reduce(0) {
return $0 + $1
}
//9
13.map 與 flatmap 的區(qū)別
1、map 可以對(duì)一個(gè)集合類型的所有元素做一個(gè)映射操作
2、和map 不同,flatmap 在之前版本有兩個(gè)定義,分別是:
func flatMap(transform: (Self.Generator.Element) throws -> T?) -> [T]
func flatMap(transform: (Self.Generator.Element) -> S) -> [S.Generator.Element]
swift 4.1 廢棄后改為
func flatMap(transform: (Self.Generator.Element) throws -> Sequence) -> [Sequence.Element]
func flatMap<U>(_ transform: (Wrapped) throws -> U?) rethrows -> U?
1) flatMap的第一個(gè)作用和map一樣,對(duì)一個(gè)集合類型的所有元素做一個(gè)映射操作,但是可以過濾為nil的情況
例如:
let array = [1,2,5,6,7,nil]
let array_map = array.map { $0 }
//[Optional(1), Optional(2), Optional(5), Optional(6), Optional(7), nil]
let array_flatmap = array_map.flatMap { $0 }
//[1, 2, 5, 6, 7]
2) 第二種情況可以進(jìn)行“降維”操作
let array = [["1", "2"],["3", "4"]]
let array_map = array.map { $0 }
//[["1", "2"], ["3", "4"]]
let array_flatmap = array_map.flatMap { $0 }
//["1", "2", "3", "4"]
14.什么是 copy on write
copy on write, 寫時(shí)復(fù)制,簡(jiǎn)稱COW,它通過淺拷貝(shallow copy)只復(fù)制引用而避免復(fù)制值;當(dāng)?shù)拇_需要進(jìn)行寫入操作時(shí),首先進(jìn)行值拷貝,在對(duì)拷貝后的值執(zhí)行寫入操作,這樣減少了無謂的復(fù)制耗時(shí)。
15.如何獲取當(dāng)前代碼的函數(shù)名和行號(hào)
#function
#line
#file
#column
16.如何聲明一個(gè)只能被類 conform 的 protocol
protocol:class
17.String 與 NSString 的關(guān)系與區(qū)別
兩者可以隨意轉(zhuǎn)換
String為值類型,拷貝賦值需要值拷貝
NSString 傳遞指針
20.如何截取 String 的某段字符串
substring 已廢棄
let star = str.index(str.startIndex, offsetBy: 0)
let end = str.index(str.startIndex, offsetBy: 4)
let substr = str[star..<end]
21.throws 和 rethrows 的用法與作用
當(dāng)閉包參數(shù)會(huì)拋出異常時(shí) 使用throws
同時(shí)外部方法體返回結(jié)果需要 rethrows 異常
rethrows 可以用 throws 替換, 反過來不行
22.try? 和 try!是什么意思
不處理錯(cuò)誤,拋出異常函數(shù)時(shí), 如果函數(shù)拋出異常, 則返回 nil, 否則返回函數(shù)返回值的可選值,
保證不會(huì)出現(xiàn)錯(cuò)誤 強(qiáng)制解,拋出異常的時(shí)候崩潰, 否則則返會(huì)函數(shù)返回值
23.associatedtype 的作用
關(guān)聯(lián)類型,關(guān)聯(lián)類型為協(xié)議中的某個(gè)類型提供了一個(gè)別名,其代表的真實(shí)類型在實(shí)現(xiàn)者中定義
//協(xié)議,使用關(guān)聯(lián)類型
protocol TableViewCell {
associatedtype T
func updateCell(_ data: T)
}
//遵守TableViewCell
class MyTableViewCell: UITableViewCell, TableViewCell {
typealias T = Model
func updateCell(_ data: Model) {
// do something ...
}
}
24.public 和 open 的區(qū)別
是否可以繼承
25.聲明一個(gè)只有一個(gè)參數(shù)沒有返回值閉包的別名
typealias MyBlock = (Int) -> (Void)
26.Self 的使用場(chǎng)景
例如:協(xié)議定義的時(shí)候,如果需要使用到實(shí)現(xiàn)者的上下文怎么辦? 我們并不知道誰會(huì)實(shí)現(xiàn)自己
這個(gè)時(shí)候可以使用Self進(jìn)行指代
27.dynamic 的作用
swift中的函數(shù)是靜態(tài)調(diào)用,靜態(tài)調(diào)用的方式會(huì)更快,但是靜態(tài)調(diào)用的時(shí)候沒救不能從字符串查找到對(duì)于的方法地址,這樣 與OC交互的時(shí)候,OC動(dòng)態(tài)查找方法就會(huì)找不到,這個(gè)時(shí)候就可以通過使用 dynamic 標(biāo)記來告訴編譯器,這個(gè)方法要被動(dòng)態(tài)調(diào)用的
swift中如果KVO監(jiān)聽屬性,那么屬性就需要 dynamic 來標(biāo)記
28.什么時(shí)候使用 @objc
與OC 的交互部分
KOV 監(jiān)聽、動(dòng)態(tài)方法查找等都需要
協(xié)議可選方法等
29.Optional(可選型) 是用什么實(shí)現(xiàn)的
枚舉 一個(gè) 為nil,一個(gè)為屬性值
30.如何自定義下標(biāo)獲取
extension Demo {
subscript(index: Int) -> Int {
get {
// 返回一個(gè)適當(dāng)?shù)?Int 類型的值
}
set(newValue) {
// 執(zhí)行適當(dāng)?shù)馁x值操作
}
}
}
31.inout 的作用
讓輸入?yún)?shù)可變 類似__block 的作用
32.Error 如果要兼容 NSError 需要做什么操作
Error是一個(gè)協(xié)議, swift中的Error 都是enum, 可以轉(zhuǎn) NSError
如果需要Error有NSError的功能,實(shí)現(xiàn) LocalizedError CustomNSError 協(xié)議
33.下面的代碼都用了哪些語法糖
[1, 2, 3].map{ $0 * 2 }
array語法糖
尾部閉包語法糖
$0
34.什么是高階函數(shù)
map、flatMap、filter、reduce?
35.下面的代碼會(huì)不會(huì)崩潰,說出原因
var mutableArray = [1,2,3]
for _ in mutableArray {
mutableArray.removeLast()
}
不會(huì),值類型
36.給集合中元素是字符串的類型增加一個(gè)擴(kuò)展方法,應(yīng)該怎么聲明
extension Array where Element == String { }
37.定義靜態(tài)方法時(shí)關(guān)鍵字 static 和 class 有什么區(qū)別
非class類型 一般 統(tǒng)一用 static 例如 枚舉 結(jié)構(gòu)體
protocol中 使用 static ,實(shí)現(xiàn)協(xié)議的 枚舉 結(jié)構(gòu)體 用 static
class 中使用 class static 都可以
38.一個(gè) Sequence 的索引是不是一定從 0 開始?
39.數(shù)組都實(shí)現(xiàn)了哪些協(xié)議
Decodable Encodable Equatable Hashable CustomStringConvertible, CustomDebugStringConvertible RandomAccessCollection, MutableCollection RangeReplaceableCollection CustomReflectable ExpressibleByArrayLiteral
40.如何自定義模式匹配
infix operator =~
func =~ (str: String, pattern: String) -> Bool {
}
infix、 prefix、 postfix 用于自定義表達(dá)式的聲明, 分別表示 中綴、前綴、后綴
41.autoclosure 的作用
自動(dòng)閉包,將參數(shù)自動(dòng)封裝為閉包參數(shù)
42.下面代碼中 mutating 的作用是什么
struct Person {
var name: String {
mutating get {
return store
}
}
}
結(jié)構(gòu)體中的 屬性可能發(fā)生改變
43.如何讓自定義對(duì)象支持字面量初始化
ExpressibleByArrayLiteral
ExpressibleByStringLiteral
44.為什么數(shù)組索引越界會(huì)崩潰,而字典用下標(biāo)取值時(shí) key 沒有對(duì)應(yīng)值的話返回的是 nil 不會(huì)崩潰。
struct Array<Element> {
subscript(index: Int) -> Element
}
struct Dictionary<Key: Hashable, Value> {
subscript(key: Key) -> Value?
}
45.一個(gè)函數(shù)的參數(shù)類型只要是數(shù)字(Int、Float)都可以,要怎么表示。
Int、Float 都有一個(gè)協(xié)議
func myMethod<T>(_ value: T) where T: Numeric {
print(value + 1)
}
或者 ExpressibleByIntegerLiteral 協(xié)議也行
46.Swift的靜態(tài)派發(fā)
很顯然靜態(tài)派發(fā)是一種更高效的方法,因?yàn)殪o態(tài)派發(fā)免去了查表操作。
不過靜態(tài)派發(fā)是有條件的,方法內(nèi)部的代碼必須對(duì)編譯器透明,并且在運(yùn)行時(shí)不能被更改,這樣編譯器才能幫助我們。
Swift 中的值類型不能被繼承,也就是說值類型的方法實(shí)現(xiàn)不能被修改或者被復(fù)寫,因此值類型的方法滿足靜態(tài)派發(fā)的要求。
默認(rèn)靜態(tài)派發(fā),如果需要滿足動(dòng)態(tài)派發(fā),需要 dymanic修飾
47.Swift有哪些修飾符
open、public 、internal、fileprivate、private
48、實(shí)現(xiàn)一個(gè)函數(shù),輸入是任一整數(shù),輸出要返回輸入的整數(shù) + 2
func plusTwo(one: Int) -> (Int) -> Int {
return { (two: Int) in return two + one }
}
plusTwo(one: 4)(2)
49、Swift 到底是面向?qū)ο筮€是函數(shù)式的編程語言?
Swift 既是面向?qū)ο蟮模质呛瘮?shù)式的編程語言。
說 Swift 是 Object-oriented,是因?yàn)?Swift 支持類的封裝、繼承、和多態(tài),從這點(diǎn)上來看與 Java 這類純面向?qū)ο蟮恼Z言幾乎毫無差別。
說 Swift 是函數(shù)式編程語言,是因?yàn)?Swift 支持 map, reduce, filter, flatmap 這類去除中間狀態(tài)、數(shù)學(xué)函數(shù)式的方法,更加強(qiáng)調(diào)運(yùn)算結(jié)果而不是中間過程。
50、class 和 struct 的區(qū)別
class 引用類型,可以繼承、多態(tài),通過引用計(jì)數(shù)來管理
struct 是值類型,不通過引用計(jì)數(shù)來管理
51 swift版本協(xié)議通信方式
1、定義一個(gè)Mudule管理者,處理注冊(cè)module,獲取module
2、定義一個(gè)Module倉庫,構(gòu)建單例,處理Module注冊(cè)事件以及初始化事件,mudule按字符串方式存入字典,block作為value,muduleName作為key
3、定義一套Module協(xié)議,構(gòu)建注冊(cè)初始化方法,application分發(fā)方法
4、各模塊的對(duì)外module入口需要實(shí)現(xiàn)此協(xié)議,可以不限于大模塊,比如一個(gè)業(yè)務(wù)大模塊庫分多個(gè)小部分模塊,就可以多個(gè)小模塊單獨(dú)module
注冊(cè)module通過協(xié)議注冊(cè),注冊(cè)后管理者匯總,匯總后Appdelegate 注冊(cè)Module,module名稱配置在列表里,通過字符串轉(zhuǎn)類型將module構(gòu)建,然后調(diào)用module的注冊(cè)方法初始化module
外部訪問之間只通過module溝通,降低耦合,參數(shù)拼裝可以public 也可以通過字典等方式,回調(diào)也可以publi 閉包等操作
52、 路由地址組件通信方式
通過注冊(cè)u(píng)rlpath + 閉包 來通信
但是url的方式就是安全性較低,比如我刪掉一半,編譯正常走,但是執(zhí)行的時(shí)候肯定報(bào)錯(cuò),無法發(fā)現(xiàn)潛在bug,并且需要去注冊(cè)&
維護(hù)路由表
path也不好管理,太過凌亂,沒有以模塊為主體
依賴程序員自己發(fā)現(xiàn)
53、Target-Action
需要按規(guī)則 寫target - action,通過反射去查找target 和 action,不需要注冊(cè) 維護(hù)了,但是無法解決潛在bug問題,且必須準(zhǔn)守命名規(guī)則寫target和action