2020年iOS面試反思總結

最近應該有很多小伙伴去跳槽面試的吧丹锹,相信各位有的已經(jīng)順利收到offer了,而有些則是碰壁了,那么我在這里給大家準備了相關面試資料精钮,還有相關算法資料。想了解的可找我拿這篇文章給大家總結了在iOS面試的時候可能會遇到的技術面試題剃斧,以及這些面試題答案轨香,這些答案只是給大家一些參考,大家可以再結合自己理解進行回答幼东,有需要的朋友們下面來一起看看吧臂容。

1. 給一個數(shù)組,要求寫一個函數(shù)根蟹,交換數(shù)組中的兩個元素

  • 二X程序員:
    好簡單啊脓杉,直接寫出以下結果
func swap(_ nums: inout [Int], _ p: Int, _ q: Int) {
    let temp = nums[p]
    nums[p] = nums[q]
    nums[q] = temp 
}
  • 普通程序員:
    首先跟面試官溝通,是什么類型的數(shù)組娜亿?面試官會說丽已,任意。普通程序員微微一笑买决,寫出以下代碼
func swap<T>(_ nums: inout [T], _ p: Int, _ q: Int) {
    let temp = nums[p]
    nums[p] = nums[q]
    nums[q] = temp 
}
  • 文藝程序員:
    與面試官溝通沛婴,是什么類型的數(shù)組?有什么其他要求和限制督赤?面試官會說嘁灯,這是一個Swift面試題。文藝程序員心領神會躲舌,于是寫出以下答案:
func swap<T>(_ nums: inout [T], _ p: Int, _ q: Int) {
    (nums[p], nums[q]) = (nums[q], nums[p])
}

同時對以上代碼寫上相應測試丑婿,檢測各種邊界情況,再確認無誤后,才會說羹奉,這道題目我完成了秒旋。
這道題目看似簡單,實際上考察了程序員的審題诀拭、交流迁筛、以及測試的意識。技術上考察了Swift的泛型和Tuple的性質(zhì)耕挨。

2. 下面代碼有什么問題

public class Node {
  public var value: Int
  public var prev: Node?
  public var post: Node?

  public init(_ value: Int) {
    self.value = value
  }
}

答案:應該在 var prev 或者 var post 前面加上 weak细卧。
原因:表面上看,以上代碼毫無問題筒占。但是我這樣一寫贪庙,問題就來了:

let head = Node(0)
let tail = Node(1)
head.post = tail
tail.prev = head

此時,head 和 tail 互相指向翰苫,形成循環(huán)引用(retain cycle)止邮。

3. 實現(xiàn)一個函數(shù),輸入是任一整數(shù)奏窑,輸出要返回輸入的整數(shù) + 2

這道題很多人上來就這樣寫:

func addTwo(_ num: Int) -> Int {
    return num + 2
}

接下來面試官會說农尖,那假如我要實現(xiàn) + 4 呢?程序員想了一想良哲,又定義了另一個方法:

func addFour(_ num: Int) -> Int {
    return num + 4
}

這時面試官會問,假如我要實現(xiàn)返回 + 6, + 8 的操作呢助隧?能不能只定義一次方法呢筑凫?正確的寫法是利用 Swift 的柯西特性:

func add(_ num: Int) -> (Int) -> Int {
  return { val in
    return num + val
  }
}

let addTwo = add(2), addFour = add(4), addSix = add(6), addEight = add(8)

4. 精簡以下代碼

func divide(dividend: Double?, by divisor: Double?) -> Double? { 
  if dividend == nil { 
    return nil 
  }  
  if divisor == nil { 
    return nil 
  } 
  if divisor == 0 { 
    return nil
  }  
  return dividend! / divisor!
}

這題考察的是guard let語句以及optional chaining,最佳答案是:

func divide(dividend: Double?, by divisor: Double?) -> Double? { 
    guard let dividend = dividend, let divisor = divisor, divisor != 0 else {
        return nil
    }

    return dividend / divisor
}

5. 以下函數(shù)會打印出什么并村?

var car = "Benz" 
let closure = { [car] in 
  print("I drive \(car)")
} 
car = "Tesla" 
closure()

因為 clousre已經(jīng)申明將car 復制進去了([car])巍实,此時clousre 里的 car是個局部變量,不再與外面的car有關哩牍,所以會打印出”I drive Benz”棚潦。
此時面試官微微一笑,將題目略作修改如下:

var car = "Benz" 
let closure = {
  print("I drive \(car)")
} 
car = "Tesla" 
closure()

此時 closure沒有申明復制拷貝car膝昆,所以clousre 用的還是全局的 car 變量丸边,此時將會打印出 “I drive Tesla”

6. 以下代碼會打印出什么?

protocol Pizzeria { 
  func makePizza(_ ingredients: [String])
  func makeMargherita()
} 

extension Pizzeria { 
  func makeMargherita() { 
    return makePizza(["tomato", "mozzarella"]) 
  }
}

struct Lombardis: Pizzeria { 
  func makePizza(_ ingredients: [String]) { 
    print(ingredients)
  } 
  func makeMargherita() {
    return makePizza(["tomato", "basil", "mozzarella"]) 
  }
}

let lombardis1: Pizzeria = Lombardis()
let lombardis2: Lombardis = Lombardis() 
lombardis1.makeMargherita()
lombardis2.makeMargherita()

答案:打印出如下兩行

[“tomato”, “basil”, “mozzarella”]
[“tomato”, “basil”, “mozzarella”]
Lombardis的代碼中荚孵,重寫了makeMargherita的代碼妹窖,所以永遠調(diào)用的是Lombardis中的 makeMargherita

再進一步收叶,我們把 protocol Pizzeria中的 func makeMargherita()刪掉骄呼,代碼變?yōu)?/p>

protocol Pizzeria {
  func makePizza(_ ingredients: [String])
}

extension Pizzeria {
  func makeMargherita() {
    return makePizza(["tomato", "mozzarella"])
  }
}

struct Lombardis: Pizzeria {
  func makePizza(_ ingredients: [String]) {
    print(ingredients)
  }
  func makeMargherita() {
    return makePizza(["tomato", "basil", "mozzarella"])
  }
}

let lombardis1: Pizzeria = Lombardis()
let lombardis2: Lombardis = Lombardis()
lombardis1.makeMargherita()
lombardis2.makeMargherita()

這時候打印出如下結果:
[“tomato”, “mozzarella”]
[“tomato”, “basil”, “mozzarella”]
因為lombardis1Pizzeria,而 makeMargherita()有默認實現(xiàn),這時候我們調(diào)用默認實現(xiàn)蜓萄。

7. Swift 中定義常量和 Objective-C 中定義常量有什么區(qū)別隅茎?

一般人會覺得沒有差別,因為寫出來好像也確實沒差別嫉沽。
OC是這樣定義常量的:

const int number = 0; 

Swift 是這樣定義常量的:

let number = 0

首先第一個區(qū)別辟犀,OC中用 const來表示常量,而 Swift 中用let來判斷是不是常量耻蛇。
上面的區(qū)別更進一步說踪蹬,OC中 const 表明的常量類型和數(shù)值是在compilation time 時確定的;而 Swift 中 let只是表明常量(只能賦值一次)臣咖,其類型和值既可以是靜態(tài)的跃捣,也可以是一個動態(tài)的計算方法,它們在runtime時確定的夺蛇。

8. Swift 中 struct 和 class 什么區(qū)別疚漆?舉個應用中的實例

struct是值類型,class是引用類型刁赦。
看過WWDC的人都知道娶聘,struct 是蘋果推薦的,原因在于它在小數(shù)據(jù)模型傳遞和拷貝時比 class 要更安全甚脉,在多線程和網(wǎng)絡請求時尤其好用丸升。我們來看一個簡單的例子:

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 沒有影響。

9. Swift 到底是面向?qū)ο筮€是函數(shù)式的編程語言郊霎?

這里有一個iOS交流圈:[891 488 181] 有興趣的都可以來了解沼头,分享BAT,阿里面試題、面試經(jīng)驗书劝,討論技術进倍,裙里資料直接下載就行, 大家一起交流學習成長庄撮!

Swift 既是面向?qū)ο蟮谋嘲疲质呛瘮?shù)式的編程語言。
說 Swift 是 Object-oriented洞斯,是因為 Swift 支持類的封裝毡庆、繼承坑赡、和多態(tài),從這點上來看與 Java 這類純面向?qū)ο蟮恼Z言幾乎毫無差別么抗。
說 Swift 是函數(shù)式編程語言毅否,是因為 Swift 支持 map, reduce, filter, flatmap這類去除中間狀態(tài)、數(shù)學函數(shù)式的方法蝇刀,更加強調(diào)運算結果而不是中間過程螟加。

什么是多態(tài)?什么是分類?什么是協(xié)議?

答:
多態(tài)在面向?qū)ο笳Z言中指同一個接口有多種不同的實現(xiàn)方式,在OC中,多態(tài)則是不同對象對同一消息的不同響應方式;子類通過重寫父類的方法來改變同一方法的實現(xiàn).體現(xiàn)多態(tài)性
通俗來講: 多態(tài)就父類類型的指針指向子類的對象,在函數(shù)(方法)調(diào)用的時候可以調(diào)用到正確版本的函數(shù)(方法)。
多態(tài)就是某一類事物的多種形態(tài).繼承是多態(tài)的前提;

答:
分類: 在不修改原有類代碼的情況下,可以給類添加方法
Categroy 給類擴展方法,或者關聯(lián)屬性, Categroy底層結構也是一個結構體:內(nèi)部存儲這結構體的名字,那個類的分類,以及對象和類方法列表,協(xié)議,屬性信息
通過Runtime加載某個類的所有Category數(shù)據(jù)
把所有Category的方法吞琐、屬性捆探、協(xié)議數(shù)據(jù),合并到一個大數(shù)組中后面參與編譯的Category數(shù)據(jù)站粟,會在數(shù)組的前面
將合并后的分類數(shù)據(jù)(方法黍图、屬性、協(xié)議)奴烙,插入到類原來數(shù)據(jù)的前面

答:
協(xié)議:協(xié)議是一套標準助被,這個標準中聲明了很多方法,但是不關心具體這些方法是怎么實現(xiàn)的切诀,具體實現(xiàn)是由遵循這個協(xié)議的類去完成的揩环。
在OC中,一個類可以實現(xiàn)多個協(xié)議幅虑,通過協(xié)議可以彌補單繼承的缺陷但是協(xié)議跟繼承不一樣丰滑,協(xié)議只是一個方法列表,方法的實現(xiàn)得靠遵循這個協(xié)議的類去實現(xiàn)倒庵。

文章到這里就結束了吨枉,如果你有什么意見和建議歡迎給我留言。關于面試問題的資料有興趣可以加我了解或者咨詢問題

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末哄芜,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子柬唯,更是在濱河造成了極大的恐慌认臊,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件锄奢,死亡現(xiàn)場離奇詭異失晴,居然都是意外死亡,警方通過查閱死者的電腦和手機拘央,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進店門涂屁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人灰伟,你說我怎么就攤上這事拆又∪逖” “怎么了?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵帖族,是天一觀的道長栈源。 經(jīng)常有香客問我,道長竖般,這世上最難降的妖魔是什么甚垦? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮涣雕,結果婚禮上艰亮,老公的妹妹穿的比我還像新娘。我一直安慰自己挣郭,他們只是感情好迄埃,可當我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著丈屹,像睡著了一般调俘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上旺垒,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天彩库,我揣著相機與錄音,去河邊找鬼先蒋。 笑死骇钦,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的竞漾。 我是一名探鬼主播眯搭,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼业岁!你這毒婦竟也來了鳞仙?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤笔时,失蹤者是張志新(化名)和其女友劉穎棍好,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體允耿,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡借笙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了较锡。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片业稼。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖蚂蕴,靈堂內(nèi)的尸體忽然破棺而出低散,到底是詐尸還是另有隱情俯邓,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布谦纱,位于F島的核電站看成,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏跨嘉。R本人自食惡果不足惜川慌,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望祠乃。 院中可真熱鬧梦重,春花似錦、人聲如沸亮瓷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽嘱支。三九已至蚓胸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間除师,已是汗流浹背沛膳。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留汛聚,地道東北人锹安。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像倚舀,于是被迫代替她去往敵國和親叹哭。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,446評論 2 348

推薦閱讀更多精彩內(nèi)容