# Swift學習 # 簡單面試題

1.什么是函數式編程?

函數式編程其實是一種編程思想, 代碼寫出來只是它的表現形式

在面向對象的編程思想中, 我們將要解決的一個個問題, 抽象成一個個類, 通過給類定義屬性和方法, 讓類幫助我們解決需要處理的問題.(其實面向對象也叫命令式編程, 就像給對象下一個個命令)

而在函數式編程中, 我們則通過函數描述我們要解決的問題, 以及解決問題需要怎樣的方案.

RxSwift

2.swift相對于OC有哪些優點?

1、swift語法簡單易讀、代碼更少,更加清晰、易于維護

2、更加安全,optional的使用更加考驗程序員對代碼安全的掌控

3、泛型、結構體、枚舉都很強大

4、函數為一等公民,便捷的函數式編程

5、有命名空間 基于module

6、類型判斷

oc的優點、運行時

3.什么是泛型,swift在哪些地方使用了泛型?

泛型(generic)可以使我們在程序代碼中定義一些可變的部分,在運行的時候指定。使用泛型可以最大限度地重用代碼、保護類型的安全以及提高性能。

例如 optional 中的 map、flatMap 、?? (泛型加逃逸閉包的方式,做三目運算)

4.defer、guard的作用?

defer 包體中的內容一定會在離開作用域的時候執行

guard 過濾器,攔截器

5.swift語法糖 ?!的本質(實現原理)

? 為optional的語法糖

Optional< T > 是一個包含了 nil 和 普通類型的枚舉,確保使用者在變量為nil的情況下的處理

!  為optional 強制解包 的語法糖

6.舉例swift中模式匹配的作用?

模式匹配: 在switch中體現最明顯

通配符模式: _

標識符模式:let i = 1

值綁定模式:case .Student(let name) 或者 case let .Student(name)

元祖模式:case (let code, _)

可選模式:if case let x? = someOptional { }

類型轉換模式:case is Int:  或者  case let n as String:

表達式模式:范圍匹配 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的區別?

1、closure是匿名函數、block是一個結構體對象

2、都能捕獲變量

3、closure通過逃逸閉包來在block內部修改變量,block 通過 __block 修飾符

8.什么是capture list,舉例說明用處?

捕獲列表

weak  unowned

9.swift中private與fileprivate的區別?

private的作用域被約束與被定義的當前類作用域,fileprivate作用域是整個文件

10.Set 獨有的方法有哪些?

intersect(_:)// 根據兩個集合中都包含的值創建的一個新的集合
exclusiveOr(_:) // 根據只在一個集合中但不在兩個集合中的值創建一個新的集合
union(_:) // 根據兩個集合的值創建一個新的集合
subtract(_:) //根據不在該集合中的值創建一個新的集合

isSubsetOf(_:) //判斷一個集合中的值是否也被包含在另外一個集合中
isSupersetOf(_:) //判斷一個集合中包含的值是否含有另一個集合中所有的值
isStrictSubsetOf(:) isStrictSupersetOf(:) //判斷一個集合是否是另外一個集合的子集合或者父集合并且和特定集合不相等
isDisjointWith(_:) //判斷兩個集合是否不含有相同的值

11.實現一個 min 函數,返回兩個元素較小的元素

func minNum<T: Comparable>(a: T, b: T) -> T {
    return a > b ? a : b
}

12.map、filter、reduce 的作用

1、map 是Array類的一個方法,我們可以使用它來對數組的每個元素進行轉換
let intArray = [1, 3, 5]
let stringArr = intArray.map {
            return "\($0)"
        }
// ["1", "3", "5"]

2、filter 用于選擇數組元素中滿足某種條件的元素
let filterArr = intArray.filter {
    return $0 > 1
}
//[3, 5]

3、reduce 把數組元素組合計算為一個值
let result = intArray.reduce(0) {
    return $0 + $1
}
//9

13.map 與 flatmap 的區別

1、map 可以對一個集合類型的所有元素做一個映射操作


2、和map 不同,flatmap 在之前版本有兩個定義,分別是:
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的第一個作用和map一樣,對一個集合類型的所有元素做一個映射操作,但是可以過濾為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) 第二種情況可以進行“降維”操作

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, 寫時復制,簡稱COW,它通過淺拷貝(shallow copy)只復制引用而避免復制值;當的確需要進行寫入操作時,首先進行值拷貝,在對拷貝后的值執行寫入操作,這樣減少了無謂的復制耗時。

15.如何獲取當前代碼的函數名和行號

#function
#line
#file
#column

16.如何聲明一個只能被類 conform 的 protocol

protocol:class

17.String 與 NSString 的關系與區別

兩者可以隨意轉換

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 的用法與作用

當閉包參數會拋出異常時 使用throws

同時外部方法體返回結果需要  rethrows 異常

rethrows 可以用 throws 替換, 反過來不行

22.try? 和 try!是什么意思

不處理錯誤,拋出異常函數時, 如果函數拋出異常, 則返回 nil, 否則返回函數返回值的可選值,


保證不會出現錯誤 強制解,拋出異常的時候崩潰, 否則則返會函數返回值

23.associatedtype 的作用

關聯類型,關聯類型為協議中的某個類型提供了一個別名,其代表的真實類型在實現者中定義


//協議,使用關聯類型
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 的區別

是否可以繼承

25.聲明一個只有一個參數沒有返回值閉包的別名

typealias MyBlock = (Int) -> (Void)

26.Self 的使用場景

例如:協議定義的時候,如果需要使用到實現者的上下文怎么辦? 我們并不知道誰會實現自己

這個時候可以使用Self進行指代

27.dynamic 的作用

swift中的函數是靜態調用,靜態調用的方式會更快,但是靜態調用的時候沒救不能從字符串查找到對于的方法地址,這樣 與OC交互的時候,OC動態查找方法就會找不到,這個時候就可以通過使用 dynamic 標記來告訴編譯器,這個方法要被動態調用的

swift中如果KVO監聽屬性,那么屬性就需要 dynamic 來標記

28.什么時候使用 @objc

與OC 的交互部分

KOV 監聽、動態方法查找等都需要

協議可選方法等

29.Optional(可選型) 是用什么實現的

枚舉 一個 為nil,一個為屬性值

30.如何自定義下標獲取

extension Demo {
   subscript(index: Int) -> Int {
      get {
        // 返回一個適當的 Int 類型的值
      }
      set(newValue) {
        // 執行適當的賦值操作
      }
    }
}

31.inout 的作用

讓輸入參數可變 類似__block 的作用

32.Error 如果要兼容 NSError 需要做什么操作

Error是一個協議, swift中的Error 都是enum, 可以轉 NSError

如果需要Error有NSError的功能,實現 LocalizedError CustomNSError 協議

33.下面的代碼都用了哪些語法糖

[1, 2, 3].map{ $0 * 2 }

array語法糖

尾部閉包語法糖

$0

34.什么是高階函數

map、flatMap、filter、reduce?

35.下面的代碼會不會崩潰,說出原因

var mutableArray = [1,2,3]
for _ in mutableArray {
    mutableArray.removeLast()
}

不會,值類型

36.給集合中元素是字符串的類型增加一個擴展方法,應該怎么聲明

extension Array where Element == String { }

37.定義靜態方法時關鍵字 static 和 class 有什么區別

非class類型 一般 統一用 static  例如  枚舉 結構體

protocol中 使用 static ,實現協議的 枚舉 結構體 用 static

class 中使用  class static 都可以

38.一個 Sequence 的索引是不是一定從 0 開始?


39.數組都實現了哪些協議

Decodable Encodable Equatable Hashable  CustomStringConvertible, CustomDebugStringConvertible RandomAccessCollection, MutableCollection RangeReplaceableCollection CustomReflectable ExpressibleByArrayLiteral

40.如何自定義模式匹配

infix operator =~

func =~ (str: String, pattern: String) -> Bool {
    
}

infix、  prefix、  postfix  用于自定義表達式的聲明, 分別表示 中綴、前綴、后綴  

41.autoclosure 的作用

自動閉包,將參數自動封裝為閉包參數

42.下面代碼中 mutating 的作用是什么

struct Person {

    var name: String {
        mutating get {
            return store
        }
    }
}

結構體中的 屬性可能發生改變

43.如何讓自定義對象支持字面量初始化

ExpressibleByArrayLiteral


ExpressibleByStringLiteral

44.為什么數組索引越界會崩潰,而字典用下標取值時 key 沒有對應值的話返回的是 nil 不會崩潰。

struct Array<Element> {
    subscript(index: Int) -> Element
}

struct Dictionary<Key: Hashable, Value> {
    subscript(key: Key) -> Value?
}

45.一個函數的參數類型只要是數字(Int、Float)都可以,要怎么表示。

Int、Float 都有一個協議

func myMethod<T>(_ value: T) where T: Numeric {
    print(value + 1)
} 

或者 ExpressibleByIntegerLiteral 協議也行

46.Swift的靜態派發

很顯然靜態派發是一種更高效的方法,因為靜態派發免去了查表操作。

不過靜態派發是有條件的,方法內部的代碼必須對編譯器透明,并且在運行時不能被更改,這樣編譯器才能幫助我們。

Swift 中的值類型不能被繼承,也就是說值類型的方法實現不能被修改或者被復寫,因此值類型的方法滿足靜態派發的要求。

默認靜態派發,如果需要滿足動態派發,需要 dymanic修飾

47.Swift有哪些修飾符

open、public 、internal、fileprivate、private

48、實現一個函數,輸入是任一整數,輸出要返回輸入的整數 + 2

func plusTwo(one: Int) -> (Int) -> Int {
    return { (two: Int) in return two + one }
}

plusTwo(one: 4)(2)

49、Swift 到底是面向對象還是函數式的編程語言?

Swift 既是面向對象的,又是函數式的編程語言。
說 Swift 是 Object-oriented,是因為 Swift 支持類的封裝、繼承、和多態,從這點上來看與 Java 這類純面向對象的語言幾乎毫無差別。
說 Swift 是函數式編程語言,是因為 Swift 支持 map, reduce, filter, flatmap 這類去除中間狀態、數學函數式的方法,更加強調運算結果而不是中間過程。

50、class 和 struct 的區別

class 引用類型,可以繼承、多態,通過引用計數來管理

struct 是值類型,不通過引用計數來管理

51 swift版本協議通信方式

1、定義一個Mudule管理者,處理注冊module,獲取module

2、定義一個Module倉庫,構建單例,處理Module注冊事件以及初始化事件,mudule按字符串方式存入字典,block作為value,muduleName作為key

3、定義一套Module協議,構建注冊初始化方法,application分發方法

4、各模塊的對外module入口需要實現此協議,可以不限于大模塊,比如一個業務大模塊庫分多個小部分模塊,就可以多個小模塊單獨module

注冊module通過協議注冊,注冊后管理者匯總,匯總后Appdelegate 注冊Module,module名稱配置在列表里,通過字符串轉類型將module構建,然后調用module的注冊方法初始化module

外部訪問之間只通過module溝通,降低耦合,參數拼裝可以public 也可以通過字典等方式,回調也可以publi 閉包等操作

52、 路由地址組件通信方式

通過注冊urlpath + 閉包 來通信

但是url的方式就是安全性較低,比如我刪掉一半,編譯正常走,但是執行的時候肯定報錯,無法發現潛在bug,并且需要去注冊&維護路由表

path也不好管理,太過凌亂,沒有以模塊為主體

依賴程序員自己發現

53、Target-Action

需要按規則 寫target - action,通過反射去查找target 和 action,不需要注冊 維護了,但是無法解決潛在bug問題,且必須準守命名規則寫target和action

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。