介紹有哪些設計原則,並讓比較詳細的說了其中開閉原則在項目中的應用?
單一職責原則
開閉原則:OC中
category
,通過runtime
添加交換方法等,都是開閉原則里氏替換原則
接口隔離原則
依賴倒置原則
迪米特法則
組合/聚合複用原則
介紹自己的過往的項目經驗,會結合項目問一些架構向的思考
架構是解決當項目增大,開發團隊的人員越來越多,應用運營起來之後業務需求和功能需求日益增長。好的架構往往可以帶來快速開發效率,和高效的代碼管理。 我們可以看出我們的架構總是隨着項目不斷調整的,不是一塵不變的。 首先我們的架構設計應該牢記軟件的設計原則。設計原則指導我們設計易理解的API設計和建立合理依賴關係。 常見的客戶端架構有
-
MVC
MVC最大的優勢就是快速開發,當項目初期,追求快速上線的時候可以使用MVC,並且蘋果提供了MVC的官方支持,項目初期無疑選擇MVC是最佳的。
MVC結構簡單即使對於經驗不那麼豐富的開發者來講維護起來也較爲容易。
-
MVP
- 非常方便測試,因爲view功能非常少,可以很方便測試UI細節
-
MVVM
MVVM的優勢就是,任務均攤每部分都承擔各自的責任,結構清晰更加符合軟件設計原則
其次就是可測試性強,我們只需要測試ViewModel就能夠輕易的測試UI上的問題
通過觀察者模式,來進行屬性綁定,代碼量將會小的多
-
VIPER
方便測試,指責明確,更容易對每個部分進行測試。
設計更清晰,兼容性更強
同時對團隊人員要求更大,代碼量比其他幾種架構都大,並且管理要求更高。
對於組件化架構,其實脫胎於前端的設計思路,在前端SPA單頁面應用,路由起到了很關鍵的作用。路由的作用主要是保證視圖和 URL 的同步。在前端的眼裏看來,視圖是被看成是資源的一種表現。當用戶在頁面中進行操作時,應用會在若干個交互狀態中切換,路由則可以記錄下某些重要的狀態,比如用戶查看一個網站,用戶是否登錄、在訪問網站的哪一個頁面。而這些變化同樣會被記錄在瀏覽器的歷史中,用戶可以通過瀏覽器的前進、後退按鈕切換狀態。總的來說,用戶可以通過手動輸入或者與頁面進行交互來改變 URL,然後通過同步或者異步的方式向服務端發送請求獲取資源,成功後重新繪製 UI。 那麼我們把這樣的思路同樣可以引入iOS,android。既可以保證每個頁面獨立性更強,又可以保證當我們需要快速修復bug的時候可以迅速替換爲web頁面。 常見的路由,有MGJRouter等。
iOS
iOS編譯的過程和原理
編程語言分爲兩種,編譯語言和直譯式語言
編譯語言就是 必須先通過編譯器生成機器碼,機器碼可以直接在CPU上執行,執行效率較高,代表語言有 C++,OC,Swift等
直譯式語言 是在執行的時候通過一箇中間的解釋器將代碼解釋爲CPU可以執行的代碼。較編譯語言來說,直譯式語言效率低一些,但是編寫的更靈活。
iOS中編譯都是依賴於Clang(swift)
+LLVM
編譯過程 預處理 -> 詞法分析 -> 語法分析 -> 靜態分析 -> 生成彙編指令 -> 彙編 -> 鏈接 -> 生成Mach-O
文件 -> dyld
動態鏈接 -> dSYM
iOS 靜態庫和動態庫
靜態庫和動態庫是相對編譯期和運行期的:靜態庫在程序編譯時會被鏈接到目標代碼中,程序運行時將不再需要改靜態庫;而動態庫在程序編譯時並不會被鏈接到目標代碼中,只是在程序運行時才被載入,因爲在程序運行期間還需要動態庫的存在。
靜態庫:以
.a
和.framework
爲文件後綴名。動態庫:以
.tbd
(之前叫.dylib
) 和.framework
爲文件後綴名。(系統直接提供給我們的framework都是動態庫!)
介紹常用屬性修飾符,介紹 assign 和 weak 之間的區別。這塊會延伸到內存管理相關,比如引用計數的方式。
常用屬性修飾符: weak
, assign
, strong
, copy
, nonatomic
, atomic
assign
: 一般用來修飾基本的數據類型,包括基礎數據類型和C數據類型。 assign
聲明的屬性是不會增加引用計數的,聲明的屬性釋放後,屬性就不存在了。但是,指針沒有置空過程,成爲了野指針,如果新的對象被分配到了這個內存地址上,又會crash
,所以一般只用來聲明基本的數據類型。
weak
:弱引用,不增加引用計數。防止循環引用時使用,並且在所指向的對象被釋放之後,weak
指針會被設置的爲nil
。weak
引用通常是用於處理循環引用的問題,如代理及block
的使用中,相對會較多的使用到weak
。
當屬性用weak修飾時,會將該指針存入一個weak
表,該表是一個hash
表,obj爲鍵值,存儲了一組obj_weak
的地址。當屬性使用weak
修飾時,性能開銷較大。
strong
: strong
修飾的屬性一般不會自動釋放,在OC中,對象默認是強指針,當屬性用strong 引用計數自動加1,該指針指向的對象不會由於其他指針指向的改變而銷燬。
copy
: 在我們拷貝一個對象的時候,分爲深拷貝和淺拷貝。
深拷貝:對象拷貝 - 直接拷貝內容。源對象和副本對象指的是兩個不同的對象,源對象引用計數器不變,副本對象引用計數器爲1.
淺拷貝:指針拷貝 - 將指針中的地址值拷貝一份。源對象和副本對象指的都是同一個對象,對象引用計數器+1,相當於retain
.
nonatomic
:非原子操作,和atomic
相對。atomic
保證系統生成的 getter
/setter
操作的完整性。注意這裏只保證了getter
/setter
操作,使用atomic
並不是絕對線程安全的,當多個線程對該屬性進行操作的時候,也會造成錯誤。
介紹 runloop 相關的知識和在實際開發中的使用情況
RunLoop
顧名思義,是運行循環。它跟線程是一一對應的,每一個線程都有一個RunLoop
,在需要的時候創建。RunLoop
的作用很簡單,就是保持線程不會退出,並且處理一些事件。 Runloops是線程的基礎架構部分, Cocoa
和CoreFundation
都提供了 run loop
對象方便配置和管理線程的 runloop
。每個線程,包括程序的主線程都有與之相應的 runloop
對象。
推薦文集
* iOS面試題 答案合集
* BAT—最新iOS面試題總結
收錄:原文地址