Swift 面試總結(jié) (上)

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ì)的點這里

11.柯里化函數(shù)

詳細(xì)介紹

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • SwiftDay011.MySwiftimport UIKitprintln("Hello Swift!")var...
    smile麗語閱讀 4,111評論 0 6
  • Swift 介紹 簡介 Swift 語言由蘋果公司在 2014 年推出,用來撰寫 OS X 和 iOS 應(yīng)用程序 ...
    大L君閱讀 3,445評論 3 25
  • importUIKit classViewController:UITabBarController{ enumD...
    明哥_Young閱讀 4,202評論 1 10
  • 基礎(chǔ)部分(The Basics) 當(dāng)推斷浮點數(shù)的類型時,Swift 總是會選擇Double而不是Float。 結(jié)合...
    gamper閱讀 1,509評論 0 7
  • 千萬要避開三大坑:湊熱鬧,隨大流,操閑心。 不要浪費注意力。把時間投入到有積累的事情中去。 時常問自己兩個問題:什...
    okok666閱讀 249評論 0 0

友情鏈接更多精彩內(nèi)容