小米、百度、bigo 、滴滴 、快手等iOS 面試后的一次階段性總結


面試過程

在疫情期間都是遠程面試,下邊先介紹一下疫情期間面試的一些公司的面試情況。同時拿到了其中幾家的 offer。下邊介紹的面試題只還原了其中印象比較深的部分,會存在不足的情況,並不代表面試的全部。

小米

一面

  • 介紹有哪些設計原則,並讓比較詳細的說了其中開閉原則在項目中的應用。
  • 介紹設計模式,然后其中主要問了我抽象工廠和適配器兩種模式。
  • 介紹 runloop 相關的知識和在實際開發中的使用情況
  • 要求詳細的描述事件響應鏈

二面

  • 介紹過往的項目經驗,因為曾經的項目和所面試的部門崗位需求匹配度較高,所以這塊的時間占比較多。
  • 回文算法
  • (算法)判斷一個字符串是不是對稱的字符串,比如 abba 或者 aba 這樣的就是對稱的。
  • block 的實現原理
  • 比較詳細的介紹 https 的過程。
  • 過往開發中做過哪些優化向的工作,問的也比較詳細。
  • 如何檢測項目中的卡頓問題(比如假死)
  • 比較詳細的介紹消息轉發流程和事件響應鏈
  • GCD 的底層線程調度原理
  • 介紹 hash 算法的原理

三面

  • 一個二叉樹逐層打印的算法題
  • 介紹自己的過往的項目經驗,會結合項目問一些架構向的思考
  • 如果現在做一個新的網絡層框架,有哪些需要考量的點

百度

百度只有一面,因為面得是百度的商業化部門,對於細節的要求非常嚴格。個人感覺自己的表現確實不是很好。

  • 判斷一個字符串是不是 ipv6 地址(要求盡全力的考慮所有異常的情況)

PS:當時面試官明確告訴我,這個面試題做不好,面試是直接結束的。

  • 介紹界面卡頓的優化有哪些可以優化的點。

  • 介紹 UIResponder 的繼承鏈。然后說事件響應鏈。

Bigo

感覺面試的這些公司,Bigo 對於基礎的考察最全面。

一面

  • (算法)找出一個頁面中漏出部分面積最大的試圖,重合的部分按照最上層的面積算漏出,會有時間復雜度的要求。
  • 簡單地介紹的過往的項目經驗
  • 控件的點擊事件和添加在上邊的手勢誰先響應,並說明原因
  • 談 CoreAnimation 和 CoreGraphic 的區別
  • 說 @synchronized 鎖的實現原理,並說明其中可能存在的問題。同時介紹了 iOS 開發中常見的鎖。
  • 介紹編譯的過程和原理
  • 談對於 bitcode 的理解和作用。
  • 詳細的介紹了 Https 的過程。

二面

  • 介紹屬性常用修飾符,介紹 assign 和 weak 之間的區別。這塊會延伸到內存管理相關,比如引用計數的方式。
  • 聊對於 GCD 的理解,和 GCD 底層是如何進行線程調度的。聊 GCD 中常見方法的使用 (group ,信號量
    ,barrier 等)
  • 詳細的介紹了 KVC 和 KVO 的原理。
  • 介紹消息轉發過程
  • 介紹對於 Runloop 並介紹知道的應用場景。再具體場景中會有追問。
  • 介紹項目優化的經驗,這一塊會聊的比較細。
  • 介紹對於靜態庫和動態庫的理解。
  • 在 webview 使用過程中存在的問題和解決方案。

三面

  • 介紹了過往 RN 的使用經驗和對於 Flutter 的理解。
  • 談對於組件化的理解和市面上常見的組件化方案
  • 問了一些 APM 向上的問題。
  • 談個人對於項目架構選擇的理解。自己如何進行架構的選擇(主要對於 MVVM,MVC等,后文有個人對於這一塊的理解)
  • 談個人規划

滴滴

一面

滴滴的一面分為兩部分。

  • 第一部分:過往項目經驗,會對自己的過往項目經驗,結合自己的描述,面試官問你介紹到的項目中涉及到問題,然后會據此引申出一些問題,這一部分占比比較大。
  • 第二部分是基礎知識面
  • 談屬性修飾符,如果 assign 修飾對象可能存在的問題和原因。
  • 比較的深入的聊了內存管理的內容,包含引用計數和 weak 修飾的對象的內存管理的過程。問的會比較深入。
  • 講 runloop 的過往使用經驗。
  • 介紹自己比較熟悉的三方庫的實現原理

二面

  • 對於鎖的理解(自旋鎖和互斥鎖),以及 iOS 開發中常見的鎖。同時要求介紹個人在開發過程中在哪些場景下用到過鎖。
  • 在實際開發中遇到過哪些多線程問題以及如何進行解決的。
  • 為什么不能在異步線程中更新頁面,介紹原因。
  • 對於內存泄漏的了解,以及介紹知道的解決方案。
  • 一些優化向上的問題,主要是根據自己介紹的優化進行較為深入的追問。
  • 一個坦克從一個空間的起點到終點,中間在某些位置上有阻隔的情況下,判斷從起點到終點是否有可行路徑的算法題。

三面

  • 比較詳細的介紹之前的項目經驗和主要負責的內容
  • 介紹過往項目中最有挑戰的事情,並會據此深入的聊。
  • 介紹了一些架構向的理解
  • 談個人規划

快手

快手的一面是跨部門面試,二面是本部門面,所以一二面面試題會有一些重復,只寫了一次。

一面

  • 介紹過往的項目經驗
  • 兩個不算難的算法題(具體的忘記了...)
  • 聊了 assign 修飾對象可能存在的問題
  • 聊過往項目中的優化經驗
  • 介紹消息轉發流程

二面

  • 比較詳細的聊到的 block,深入的講了其中的實現原理,並介紹不同變量的引用方式。
  • 介紹開發中常見的循環引用,並說明其中的原因和解決的方案和原理。
  • 介紹 Runloop 並講應用場景。
  • 二叉樹翻轉

三面

  • 一道多線程實際場景下的問題,要求遠程寫出實現方案的代碼
  • 聊對於 MVVM,MVC 和 MVP 的理解。
  • 介紹過往項目中 RN 的使用經驗和遇到的問題。
  • 講如何將一張內存極大的圖片可以像地圖一樣的加載出來(只說實現思路)
  • 聊對於組件化的理解,對於市面上的組件化方案的理解,優劣分析等。

其他

除了上邊介紹的公司外,還面了平安,51 talk,58 同城,好未來,美篇。

因為絕大部分面試內容和上邊的基本上只是重復,只對差異性的面試題進行了總結。

  • 對圖像編解碼的了解
  • 在子線程中是如何進行內存管理的
  • JSBridge 是如何實現的,以及和原生的調用關系。
  • 問到了一些 AFNetworking 和 SDWebImage 相關的實際開發中的問題。

iOS 的一些面試准備

上邊聊完了面試過程中遇到的面試題,下邊聊聊自己在面試之前的一些准備工作。

其實這次跳槽對於個人而言是很早之前就有准備了的,所以疫情對於我的影響並不是很大。此外想突出強調的是 iOS 面試中的基礎知識在於日常的積累和總結,單純的靠面試前的短期准備個人感覺是不夠的。

下邊根據上邊的面試題和之前個人的面試准備,對整個面試過程做了一次梳理。

1.算法

《劍指 offer》 半個多月的時間用 Swift 敲了一遍,然后用 OC 手寫了一遍。

之前斷斷續續刷了 LeetCode 上 Medium 和 Easy 的題有 150+

對於國內的小伙伴,基本上客戶端面試涉及到的算法知識是足夠覆蓋的了。當然快手的三面算法題還是被虐了...

如果你正在跳槽或者正准備跳槽不妨動動小手,添加一下咱們的交流群1012951431來獲取一份詳細的大廠面試資料為你的跳槽多添一份保障。

2.基礎

其實個人認為 iOS 基礎知識部分真的需要個人日常的一些積累,在面試准備階段對整個積累的整體串聯,然后再查缺補漏的過程,下邊是我自己面試准備階段的一些知識主線。

  • 網絡

    • 1.近些年客戶端 WEB 劫持的現象依然常見。所以 DNS 是什么和相關的問題。

    其中包含從 localDNS 到 HTTPDNS 轉變目的和原因。以及在 DNS 場景中 CDN 的使用。

    • 2.對於 tcp / ip 和 http 協議,以及 SSL 和 物理層和數據鏈路層的部分協議的掌握。

    當時對於這一部分,我的准備過程就是自下而上的方式進行復習的。

    • 3.有興趣的小伙伴也可以了解一下 BFF。
  • 內存管理(對象視角)

    • 1.isa 是如何使用 bitmask 的方式來進行內存管理的,其中相關的字段有哪些。

    • 2.對象的引用計數的管理分為哪兩部分。以及思考為什么有這兩部分的設計。

    • 3.弱引用的內存管理方式。

    • 4.在分類中使用 Associate 方式添加的屬性是如何進行內存管理的。

  • 內存管理 (運行時視角)

    • 1.在主線程中的內存管理方式,其實就是 Runloop 的觸發的時機。

    • 2.如果在子線程中如何進行內存管理的。

    • 3.AutoReleasePool 的使用原理和數據結構。

  • 內存管理 (項目視角)

    • 1.項目中存在的循環引用的問題的場景和解開循環的方案。(代理,Block,timer,A-B-C-A 等)

    • 2.當下主流的內存管理的快速追溯方案有哪些,思路是什么。比如 FBRetainCycleDetector ,MLeaksFinder,PLeakSniffer。

  • 多線程問題

    • 1.iOS 開發中常用鎖的總結,以及對於自旋鎖和互斥鎖的理解。

    • 2.GCD 中的線程池的原理。串行和並行兩種隊列模型在底層實現中的區別。為什么會用到 overcommit 等。(其實這里很多是涉及到對於 GCD 相關源碼的理解),主要在於理解隊列中線程的創建和調度。

    • 3.NSOeration 的使用場景等。

    • 4.一些開發中常見的多線程問題的場景和解決方案。

  • runtime & runloop 相關的問題

    • 1.其實上邊內存管理(對象視角)下就是 runtime 中很多相關的核心代碼。

    • 2.runtime 中 method swizzle 的使用場景和可能存在的問題(比如 hook viewdidLoad 統計頁面加載市場不准確的原因)。

    • 3.消息響應鏈。

    • 4.從 isa 中的 data 的數據結構,到 class_ro_t 和 class_rw_t 的理解。如果這里的轉換過程理解足夠,是完全可以解釋為什么 category 不能添加屬性的。此外是對於內存對齊問題的理解。

    • 5.對於 runloop 的理解,以及一些常見的使用場景。(比如系統中主線程的場景和 AFNetwork 中的場景,以及主線程卡頓抓取方案的場景等等)

  • 其他

    • block 相關的知識。

    • 對於動靜態庫的在項目中結合導入可能存在的問題和解決方案,以及動態庫過多可能造成的問題等等。

    • 基於 pod 的項目管理。

    • KVC 和 KVO 的實現原理。

    • 一些跨平台方案的考察(RN 和 Flutter 其實這一部分比較錦上添花,沒有也不是一定不行),筆者之前寫過一段時間 RN 對於 Flutter 也有一些經驗。個人認為未來跨平台的方案是未來的一種趨勢。

上邊大致是我在面試之前和面試之后對於 iOS 基礎知識的梳理出來的主線。感覺不夠全面,但是面對市場上主流的 iOS 面試應該足夠了,很多同學可能對於上邊涉及的知識點會有一個問題就是面試造火箭的感覺,對於實際開發中真正能用到的東西十分有限,對於項目的實際開發,實際使用十分有限。

下邊談一下個人對於類似觀點的理解。

首先面試是一次篩選的過程,而上邊的知識點就是相對而言更有篩選的辨識度。而日常開發中所謂的扭螺絲的內容對於絕大部分開發者而言都沒有很好的區分能力。面試官在面試過程中更希望看到的是候選人在日常中的積累和學習的能力。而基礎知識的扎實是學習能力和學習意願的一種體現。

此外,其實現在的客戶端市場上,因為多年前培訓機構的原因,不缺乏初級開發者,對於大廠而言,項目的復雜度和代碼的維護成本都是很多項目很關注的點,當下市場上需要的基礎知識扎實,然后可以根據基礎知識來做各種項目優化相關的 developer。所以有一些對於基礎的要求也無可厚非。

聊到項目優化,下邊是在面試准備階段對於項目優化結合過往項目經驗和之前知識積累做的一些准備。

3.項目優化

  • 包大小管理

    • 1.對於資源的優化

      其中涉及到的一些思路,圖片的優化,圖片的壓縮,Assets -> 網絡加載的轉換,無用類和無用方法的查找分析工具的了解,以及使用 linkmap 的方式查找包各個模塊的占比,從工程視角下做代碼和架構層面的調整和優化。

    • 2.工程視角下的優化

      通過 WorkSpace 中的設置實現打包的架構的優化,刪除對於不在支持架構的打包。

    • 3.項目打包方式的優化

      開發階段有很多的輔助工具,幫助我們尋找和發現問題,甚至對於一些項目而言還存在類似模擬數據相關的很多類或者庫,這些其實對於線上項目而言是不需要的,所以可以整體上實現將對應的輔助工具整體歸整收集到一個或幾個組件,通過 #DEBUG 的方式引入,然后通過腳本的方式保證線上環境的包不包含對應庫的方式實現項目的瘦身。

  • 界面卡頓的優化

    • 1.卡頓成因

    對於卡頓成因,比較常見的有主線程中的邏輯卡頓和離屏渲染。

    關於離屏渲染個人感覺即刻團隊的總結很贊,離屏渲染優化

    • 2.快速追溯工具

    其實 Xcode 為我們提供了 instrunments 工具,但是對於線上問題的上報和追溯能力也很重要,其實這一塊就可以參考在主線程的 Runloop 中添加 Observer 來實現。當然實現過程中可能還會有堆棧抓取不全等等問題,此時可能嘗試的方向就包含 fishhook 的方式的嘗試。這個過程中又要回歸最初的很多基礎知識,這個過程就會發現,面試事的造火箭也並不是那么不可理解,因為還是有很多進階的場景下需要一些造火箭的能力...

  • 網絡層優化

    • 1.從 jpg 到 webp 格式的轉化。(新聞和資訊,電商等圖片瀏覽量大的項目)

    • 2.從 json 到 protobuffer 的優化。

    • 3.將一些收集性的數據整合打包上傳,減少請求次數,並且可以結合 Runloop 來擇機上傳。

  • 耗電量和定位相關的優化(筆者沒有對應的經驗)

  • 工程視角下的優化

    • 1.啟動階段的優化。可以看看楊瀟玉的文章

    • 2.抖音的二進制重排方案

    • 3.APM 的建設

    筆者對於 2,3 暫時沒有線上實踐經驗...

4.架構

其實聊到架構,不知道從什么時候開始 iOS 圈子里的話題就集中在了 MVC,MVP,MVVM 和 Viper 這幾種之間的比較。

由於筆者只是對於 MVC 和 MVVM 有相對多的使用,所以談談自己對於架構的理解。

個人認為這幾種架構不存在絕對意義上的孰優孰略,每一種架構都有其產生的對應的背景。而且不認為說一個項目一定就全是 MVC 或者 MVVM。或者說脫離了 RAC 就不能使用 MVVM 的方式來做設計項目中的部分代碼。

筆者個人認為,項目的架構選擇的問題上需要考量業務背景,效率方面的因素。

比如傳統的 MVC 架構,最大的槽點就在於很多人認為 view 和 model 層很輕,但是 controller 層代碼冗余較多,於是產生了 MVVM 的架構,筆者個人對於 MVVM 是這個背景下產生的說法是否定的。

筆者個人認為, 傳統的 MVC 架構如果 controller 的代碼過多最大的原因在於 developer 本身的問題,其實完全可以根據業務將對應的邏輯進行拆分分別的放到一些對應的 manager 管理類中做處理。將一個頁面拆分成更多小得 MVC 的方式來解決項目過多的在一處維護困難的問題。個人認為這樣的方式一樣可以提高代碼的可維護性。此時看 manager 很像 MVVM 中的 VM 。

筆者的觀點貌似就是在說 MVVM 的產生沒有什么價值。其實並不是這樣的。我們在聊一個架構模式的時候需要了解 MVVM 的優點。其實 MVVM 的架構設計較早的出現在前端領域。個人認為當一個頁面的交互非常多,數據傳遞鏈比較深的時候,通過 MVVM 和 RAC 的結合的方式可以大大的降低代碼的維護成本和提高代碼的可讀性,而且可以很好且方便的做狀態管理。在這種場景下使用 MVVM 是我認為很好的場景。而對於一個偏靜態的頁面而言,我並認為 MVVM 和 MVC 存在孰優孰略。從維護成本的角度考量,反而 MVC 可能更優。

所以個人認為 MVC 和 MVVM 對於一個項目而言不是二選一的關系,而是可以結合場景選擇來使用。

此外就是效率問題,對於很多項目而言,很多人說 MVVM 更好就一定要 MVVM + RAC 。我認為這有些偏激的成分存在,需要考慮團隊整體技術儲備和維護成本的整體考量。

如果組里只有一兩個人會 MVVM + RAC ,而剩下的人對於類似的知識點根本不掌握,不是說其他人不應該學習和進階。而是說應該在考量開發效率和成本,對應的選擇性放棄,之后條件允許后在逐步做遷徙。個人比較反對架構的非黑即白。

此外,想表達一點個人觀點在於大多人的關注點貌似都注意在了對於 MVVM 和 MVC 的比較之中,而忽略了設計模式和設計原則的重要性。

其實個人認為尤其是日常的業務開發,設計模式和設計原則的使用在模塊或者業務中更為重要。

筆者覺得關於設計模式和設計原則的知識可以讀讀《Objective-C 編程之道》。

此外對於改善和提高代碼能力可以看看《重構》《代碼整潔之道》。

5.成長的思考

上邊的總結的很多知識點,並不是我在准備面試的階段才去看對應的知識的,而是在日常開發中積累的知識的一次梳理和總結。將日常瑣碎不體系的積累的一次梳理和總結。

上邊的知識的獲取的途徑都很方便,網上有很多前輩有非常好的總結。比如 runtime 的部分我就是看了源碼+霜神的神經病院系列+ draveness 的很多文章來進行學習的。

筆者認為比較好的學習方式在於體系化整體的學習,而對於公眾號或者簡書文章的碎片化記憶。個人覺得當下碎片化學習的概念炒得火熱,但是碎片化的學習的核心是可以用碎片的時間高效的學習知識體系中小的點,提高學習的效率,但歸根結底,還是知識要成體系,還是要將碎片化的內容整體的串聯起來才更高效,如果只是一個個碎片化的知識,沒有整體性的視角,個人感覺隨着時間線的推移,用不了多久在不使用的情況下就被遺忘了。

然后就是優秀的源碼的學習,我在很早之前就讀過 Aspect 的源碼,代碼量不大,但是設計質量非常高,后來 JSPatch 開源的時候去讀相關的源碼,雖然不知道 Bang 神的消息轉發機制有沒有參考過 Aspect,但是發現消息轉發機制上的源碼有很多的相似之處,因為之間的積累,JSPatch 源碼的閱讀相對而言很順暢。后來自己在工作中寫一些小的工具也有過類似的嘗試。

此外個人認為技術的深度比技術的廣度更為重要。對於 iOS 端個人認為進階的方向有 Clang 和 LVVM 相關的知識,匯編,逆向等等。上述知識體系,也只有匯編有過比較多的接觸。對於一些奇怪的問題的追溯,匯編真的很好用。當然其他知識也在學習,最近戴銘老師出了一本 《iOS 變成理順核心知識點》,書的質量很高,就是深入學習的一個起點。

對於技術廣度的問題,筆者的經驗是挖掘自己的一些需求,然后根據自身的需求出發,比如 Swift 的學習之后,如果我們工作的項目還是 OC ,我們可以有一些優化的需求需要用到腳本的時候可以嘗試用 Swift 來寫腳本。或者嘗試將一些簡單一些的開源庫用 Swift 重寫。亦或者我日常對於理財和經濟學的東西較為關注,我會用 Swift 寫一些自己手機上使用的軟件,比如真實利率的計算。曾經為了利用好碎片時間用 Swift 寫過一個很簡單地 JS 編輯器等等。

其實自己后來學習 Python 的過程也是和生活中的一些需求有直接的關系,還是認為興趣是最好的老師,建立起興趣,然后在玩的過程中學習,簡單又高效。當然說起來容易,做起來對我同樣很難...

結尾

當然上邊的內容是自己對於過往經驗的一個總結,有些部分難免有片面甚至錯誤的地方,還希望大家能夠指正。

希望本文能為部分准備求職和在職的處在迷茫期的同學提供一種思路。成長永遠不可能一蹴而就,都是在不斷積累和學習中完成的厚積薄發。

之后希望和大家多多交流。

面試資料:

看完文章如果你正在跳槽或者正准備跳槽不妨動動小手,添加一下咱們的交流群1012951431來獲取一份詳細的大廠面試資料為你的跳槽多添一份保障。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM