1.Swift 到底是面向?qū)ο筮€是函數(shù)式的編程語言?
Swift 既是面向?qū)ο蟮?,又是函?shù)式的編程語言。
說 Swift 是 Object-oriented,是因為 Swift 支持類的封裝、繼承、和多態(tài),從這點上來看與 Java 這類純面向?qū)ο蟮恼Z言幾乎毫無差別。
說 Swift 是函數(shù)式編程語言,是因為 Swift 支持 map, reduce, filter, flatmap 這類去除中間狀態(tài)、數(shù)學(xué)函數(shù)式的方法,更加強(qiáng)調(diào)運算結(jié)果而不是中間過程。
1.map、filter、reduce 的作用
- map 是Array類的一個方法,我們可以使用它來對數(shù)組的每個元素進(jìn)行轉(zhuǎn)換
let intArray = [1, 3, 5]
let stringArr = intArray.map {
return "\($0)"
}
// ["1", "3", "5"]
- filter 用于選擇數(shù)組元素中滿足某種條件的元素
let filterArr = intArray.filter {
return $0 > 1
}
//[3, 5]
- reduce 把數(shù)組元素組合計算為一個值
let result = intArray.reduce(0) {
return $0 + $1
}
//9
1.map 與 flatmap 的區(qū)別
- map 可以對一個集合類型的所有元素做一個映射操作
- 對數(shù)組進(jìn)行flatmap操作,和map是沒有區(qū)別的
- 和map 不同,flatmap 有兩個定義,分別是:
func flatMap(transform: (Self.Generator.Element) throws -> T?) -> [T]
func flatMap(transform: (Self.Generator.Element) -> S) -> [S.Generator.Element]
1)第一種情況返回值類型是 T?, 實際應(yīng)用中,可以用來過濾元素為nil的情況,(內(nèi)部使用了 if-let 來對nil值進(jìn)行了過濾) 例如:
let optionalArray: [String?] = ["AA", nil, "BB", "CC"];
var optionalResult = optionalArray.flatMap{ $0 }
// ["AA", "BB", "CC"]
操作前是[String?], 操作后會變成[String]
2)第二種情況會自動去重處理
let numbersCompound = [[1,2,3],[4,5,6]];
var res = numbersCompound.map { $0.map{ $0 + 2 } }
// [[3, 4, 5], [6, 7, 8]]
var flatRes = numbersCompound.flatMap { $0.map{ $0 + 2 } }
// [3, 4, 5, 6, 7, 8]
$0.map{ $0 + 2 } 會得到[3, 4, 5], [6, 7, 8], 然后遍歷這兩個數(shù)組,將遍歷的元素拼接到一個新的數(shù)組內(nèi),最終并返回就得到了[3, 4, 5, 6, 7, 8]
2.Swift 中 struct 和 class 什么區(qū)別?舉個應(yīng)用中的實例
- struct沒有繼承的功能,而class是可以繼承的,這是面向?qū)ο笳Z言的核心能力,class當(dāng)然會有這個能力。
- struct 是值類型,class 是引用類型。體現(xiàn)在內(nèi)存使用上,struct是通過值傳遞,而class是通過引用傳遞的。
看過WWDC的人都知道,struct 是蘋果推薦的,原因在于它在小數(shù)據(jù)模型傳遞和拷貝時比 class 要更安全,在多線程和網(wǎng)絡(luò)請求時尤其好用。我們來看一個簡單的例子:
class A {
var val = 1
}
var a = A()
var b = a
b.val = 2
此時 a 的 val 也被改成了 2,因為 a 和 b 都是引用類型,本質(zhì)上它們指向同一內(nèi)存。解決這個問題的方法就是使用 struct:
struct A {
var val = 1
}
var a = A()
var b = a
b.val = 2
此時 A 是struct,值類型,b 和 a 是不同的東西,改變 b 對于 a 沒有影響。
3. Swift 中定義常量和 Objective-C 中定義常量有什么區(qū)別?
OC是這樣定義常量的:
const int number = 0;
Swift 是這樣定義常量的:
let number = 0
- OC中用 const 來表示常量,而 Swift 中用 let 來判斷是不是常量。
- OC中 const 表明的常量類型和數(shù)值是在 compilation time (編譯階段)時確定的;而 Swift 中 let 只是表明常量(只能賦值一次),其類型和值既可以是靜態(tài)的,也可以是一個動態(tài)的計算方法,它們在 runtime 時確定的。
4.Swift 中的泛型
泛型是為Swift編程靈活性的一種語法,在函數(shù)、枚舉、結(jié)構(gòu)體、類中都得到充分的應(yīng)用,它的引入可以起到占位符的作用,當(dāng)類型暫時不確定的,只有等到調(diào)用函數(shù)時才能確定具體類型的時候可以引入泛型。
我們之前實際上已經(jīng)使用過泛型,例如:Swift的Array和Dictionary類型都是泛型集。
詳細(xì)介紹點我
5.給一個數(shù)組,要求寫一個函數(shù),交換數(shù)組中的兩個元素
func swap<T>(_ nums: inout [T], _ p: Int, _ q: Int) {
(nums[p], nums[q]) = (nums[q], nums[p])
}
6.實現(xiàn)一個 min 函數(shù),返回兩個元素較小的元素
func min<T: Comparable>(_ a: T, _ b: T) -> T {
return a < b ? a: b
}
//這里一定要遵守 Comparable 協(xié)議,因為并不是所有的類型都具有“可比性”
7.guard 使用場景
- 使用 guard 來表達(dá) “提前退出”的意圖,有以下 使用場景 :
- 在驗證入口條件時
- 在成功路徑上提前退出
- 在可選值解包時(拍扁 if let..else 金字塔)
- return 和 throw 中
- 日志、崩潰和斷言中
而下面則是盡量 避免使用 的場景:
- 不要用 guard :替代瑣碎的 if..else 語句
- 不要用 guard :作為 if 的相反情況
- 不要:在 guard 的 else 語句中放入復(fù)雜代碼
具體介紹點這里
8.defer 使用場景
defer 語句用于在退出當(dāng)前作用域之前執(zhí)行代碼.例如:
手動管理資源時,比如 關(guān)閉文件描述符,或者即使拋出了錯誤也需要執(zhí)行一些操作時,就可以使用 defer 語句。
如果多個 defer 語句出現(xiàn)在同一作用域內(nèi),那么它們執(zhí)行的順序與出現(xiàn)的順序相反
func f() {
defer { print("First") }
defer { print("Second") }
defer { print("Third") }
}
f()
// 打印 “Third”
// 打印 “Second”
// 打印 “First”
9.String 與 NSString 的關(guān)系與區(qū)別
- String 是 struct,值類型。NSString 是類,引用類型。
10.Swift 訪問關(guān)鍵字
從高到低得權(quán)限控制順序如下
open > public > interal > fileprivate > private
private
swift3.0 private訪問級別所修飾的屬性或者方法只能在當(dāng)前類里訪問。
class A {
private func test() {
print("this is private function!")
}
}
class B: A {
func show() {
test()
}
}
上面代碼在swift3.0以前,可以順利編譯成功,但是在swift3.0中會編譯失敗,提示class B中test()方法不可用。
fileprivate
fileprivate是Swift3.0后新加的權(quán)限修飾符,fileprivate訪問級別所修飾的屬性或者方法在當(dāng)前的Swift源文件里可以訪問。(比如上面例子中把private改成fileprivate就不會報錯了)。
internal
internal為默認(rèn)訪問級別,可默認(rèn)不寫。internal訪問級別所修飾的屬性或方法在源代碼所在的整個模塊都可以訪問。如果是框架或者庫代碼,則在整個框架內(nèi)部都可以訪問,框架由外部代碼所引用時,則不可以訪問。如果是App代碼,也是在整個App代碼,也是在整個App內(nèi)部可以訪問。
public
可以被任何人訪問。但其他module中不可以被override和繼承,而在module內(nèi)可以被override和繼承。
open
open為swift3.0后新加權(quán)限關(guān)鍵字,可以被任何人使用,包括override和繼承。
詳細(xì)的點這里