如何正確地寫好一個界面
寫界面可以說是每位移動應用開發者的基本功,也是一位合格移動應用開發者繞不過去的坎。但就如不是每一位開發者都能夠成為合格的開發者一樣,本人在不同的團隊中發現,甚少有人能夠編寫出合格的UI代碼;而非常奇怪的是,在很多的開發者論壇上看到我們移動開發者更多關注于某個控件或者是動畫,但卻很少看到深入剖析UI機制,指導UI開發的文章。
由于界面涉及到的方面實在過于廣泛,本文不可能事無巨細,一一道來,所以本文先立足于點,深入剖析iOS UI系統中不被重視卻非常重要的機制,幫助本文讀者對iOS的UI系統有整體了解;進而以點帶面,拓展到UI邏輯設計和架構設計模式的討論;最后讀文而有所思有所得,設計開發出高效、易用、流暢的UI模塊。
本文章節如下:
- 基礎與本質:說明普遍意義上的UI系統的三大模塊,讓讀者從整體上對UI系統有清楚的認識。
- View:深入View的內部機制,View與Layer之間的關系,以及Offscreen Render;
- ViewController:講解ViewController在UI系統中所扮演的角色,以及UI架構設計中ViewController運用和實踐;
- MVC、MVP、MVVM:簡單分析三種主流的架構設計模式及其異同,并簡單提出了一些做架構設計意見和想法;
- 總結。
各章節間沒有必然的聯系,讀者可以選擇感興趣章節閱讀。
1. 基礎與本質
終端App開發區別于后端開發最大的不同,就是終端開發很大部分的邏輯是為用戶提供界面以供人機交互,即所謂的UI(User Interface)。所以所有的UI架構主要關注三大模塊:界面布局管理,渲染及動畫、事件響應;
1.1 布局管理
即在規定的坐標系統上,按照一定的層級順序位置大小排布在容器內。一個UI系統必然有個基于坐標的布局管理系統,不管是Windows、Sysbian,還是Andorid、iOS。好的布局管理機制直接影響界面邏輯實現的難易程度;
我們現在日常接觸到的App的UI坐標系統都是二維的,我們現在玩的3D游戲,受限于二維的展示屏幕,所以實質上只是三維在二維上的映射投影。我們一直在往更高的維度發展:全息影像、Hololens等等。在此可以設想下,未來我們構建界面的布局管理很可能就是基于真實三維坐標。
1.2 動畫及渲染
UI之所以叫User Interface,就是因為UI通過視覺上的展示,為用戶提供信息。這些信息的展示需要通過一系列復雜的計算,最后操作液晶體展示在顯示屏上,這一系列過程就是渲染和動畫;
下圖就是應用界面渲染到展示的流程:
引自WWDC2014 #419 Advanced Graphics and Animations for iOS Apps
這里不展開來講,推薦沒看過的同學都認真觀看,能夠很好的理解渲染流程和界面優化;
推薦資料:
WWDC2014 #419 Advanced Graphics and Animations for iOS Apps
Objc.io的文章:#Objc Issue 3:Views – Getting Pixels onto the Screen
1.3 事件響應
UI除了展示信息之外,還需要接收并響應用戶的點擊、手勢、搖晃等事件,經過一系列操作后更新展示信息,展示給用戶;正確及時地響應用戶的操作并給予反饋,是良好用戶體驗的保證。為何Android設備普遍給人的感覺比iOS設備要卡,其中一個主要的原因是iOS系統將響應用戶事件放在主線程的最高優先級。
1.4 UI系統架構
從整體理解了上述三個方面,你會對UI架構有系統認識。iOS中的UI系統架構如下:
引自WWDC2014 #419 Advanced Graphics and Animations for iOS Apps
2. View
UIView是UIKit中最基本控件,就如同NSObject基本上是Cocoa庫內所有類的基類一樣,UIView也是UIKit中所有界面控件的基類。只要你愿意,你甚至只用UIView就可以搭建你的App(不過iOS9做了約束,必須設置keyWindow的rootViewControler)。
一般來說,熟練掌握常用的UIView子類控件(如UIButton, UIImageView, UILabel等)就足以應付90%的界面編碼需要。但想要編寫出高效、優美的界面代碼,還需要更深入的了解。既然要深入,本文假設你對UIView已經有了初步的了解,至少使用寫過幾個完整的頁面;基于此設定下,本文討論聚焦于以下幾點:
- ?UIView 與 CALayer:討論UIView背后的CALayer,了解CALayer與UIView的關系及渲染流程;
- ?Offscreen Render:闡述什么是Offscreen Render(離屏渲染),以及一些避免離屏渲染的方法;
- ?UIResponser:討論UIView和UIViewController的父類UIResponser,分析iOS設備上的事件響應鏈;
- 設計與實踐:結合本人開發實踐經驗,說明在UIView應用中好的設計實踐規則;
參考:View Programming Guide for iOS
2.1 UIView 與 CALayer
我們應該都知道每個UIView都包含了一個CALayer,就算你沒直接看過CALayer,應該也使用過。比如給一個View切個圓角:view.layer.cornerRadius = 5.0f;;加個邊框:>view.layer.borderWidth = 1.0f; view.layer.borderColor = [UIColor darkGrayColor].CGColor;,這里使用的layer就是CALayer。
CALayer是QuartzCore庫內的類,是iOS上最基本的繪制單元;而UIView只是CALyer之上的封裝,更準確的來說,UIView是CALyer的簡版封裝,加上事件處理的集合類。事件處理我們下一節再討論,這里的簡版封裝如何理解,為什么不直接使用CALayer?
首先,如上一段所述,CALayer是最基本的繪制單元,每一個UIView都有一個CALayer的變量(>public var layer: CALayer { get }),UIView的渲染實質就是這個layer的渲染。我們可以看看的類定義,里面有很多屬性(變量)及方法在中可以找到幾乎一模一樣的對應;如屬性變量>frame、>hidden,方法>public func convertPoint(p: CGPoint, fromLayer l: CALayer?) -; CGPoint等;但也有更多的屬性方法是UIView所沒有的,這里就一一列舉了。我們可以看到UIView其實是把常用的接口(屬性和方法)暴露出來了,讓UIView更為易用。
其次,我們知道iOS平臺的Cocoa Touch 是源于OS X平臺的Cocoa),是在Cocoa的基礎上添加了適用于移動手機設備的手勢識別、動畫等特性;但從底層實現上來說,Cocoa Touch與Cocoa共用一套底層的庫,其中就包括了QuartCore.framework;但QuartCore.framework一開始就是為OS X設計的,所以其中有部分特性是不適合做移動設備開發的,比如最重要的坐標系統。因此,我們也就不難理解為何UIView/NSView在CALayer上做了一層封裝。
以上,是UIView于CALayer的主要的關系。
2.2 Offscreen Render
當你尚在懵懂未知的開發初期,在寫UIScrollView及其子類(UITableView、UICollectionView)時,一定會遇到滾動不流暢,經??D的情況;你認真研究代碼,發現你邏輯代碼都放到了異步線程,主線程做的都是渲染界面的活,為什么會卡頓?然后你想老手尋求幫助,老手會讓你去掉圓角、半透明和陰影之類,App又重回絲般順滑;你不知道為什么,問老手,他可能會很詳細跟你解釋一通,然后你一知半解地點點頭,腦中一片茫然;較好的情況,也許你依稀記得這么一個詞:離屏渲染(Offscreen Render)。那到底什么是Offscreen Render?為什么Offscreen Render會導致卡頓?
在第一章的1.2節中有提到渲染的流程圖,我們再更深入點,先看看最基本的渲染通道流程:
引自WWDC2014 #419 Advanced Graphics and Animations for iOS Apps
>注:iOS的GPU渲染機制是Tile-Based的,而Tile-Based GPU也是現在移動設備的主流;
我們再來看看需要Offscreen Render的渲染通道流程:
引自WWDC2014 #419 Advanced Graphics and Animations for iOS Apps
一般情況下,OpenGL會將應用提交到Render Server的動畫直接渲染顯示(基本的Tile-Based渲染流程),但對于一些復雜的圖像動畫的渲染并不能直接渲染疊加顯示,而是需要根據Command Buffer分通道進行渲染之后再組合,這一組合過程中,就有些渲染通道是不會直接顯示的;對比基本渲染通道流程和Masking渲染通道流程圖,我們可以看到到Masking渲染需要更多渲染通道和合并的步驟;而這些沒有直接顯示在屏幕的上的通道(如上圖的 Pass 1 和 Pass 2)就是Offscreen Rendering Pass。
Offscreen Render為什么卡頓,從上圖我們就可以知道,Offscreen Render需要更多的渲染通道,而且不同的渲染通道間切換需要耗費一定的時間,這個時間內GPU會閑置,當通道達到一定數量,對性能也會有較大的影響;
那哪些情況會Offscreen Render呢?
- ?drawRect
- ?layer.shouldRasterize = true;
- 有mask或者是陰影(layer.masksToBounds, layer.shadow*);
- Text(UILabel, CATextLayer, Core Text, etc)
…
注:layer.cornerRadius,layer.borderWidth,layer.borderColor并不會Offscreen Render,因為這些不需要加入Mask。
還有更多與Offscreen Render以及動畫圖形優化相關的知識,請認真觀看WWDC。
參考:
WWDC2011 #121 Understanding UIKit Rendering
WWDC2014 #419 Advanced Graphics and Animations for iOS Apps
2.3 設計與實踐
以上幾節,對View在開發過程中經常遇到,但并不容易深入理解的概念進行了討論。接下來,我想脫離View的具體概念,談談本人在View設計和開發中的一些實踐經驗;
2.3.1 精簡扁平的View層次結構
復雜的View層次結果不僅會影響渲染效率,而且也會造成代碼的臃腫,會造成不可預料的問題并且難以定位;怎么樣維護一個精簡扁平的View層次結構呢?原則如下:
1.盡量使用系統原生的控件;
如實現一個icon跟title上下布局的按鈕,很多人習慣是使用一個view包含了一個UIButton和一個UILabel。實際上更為推薦的方式是調整UIButon的contentInset/titleInset/imageInset三個參數來達到這個效果,非常簡單,并且title有UIButton上的展示方式和特性,如可以設置高亮顏色等;
又比如一個有著復雜一點布局結構的滾動界面,有些開發者會覺得使用UITableView/UICollectionView實現會比較復雜,有些效果可能沒辦法達到,就用他們的基類UIScrollView來實現,自己造了一大套的輪子,代碼可能也變得非常復雜;實際上根據我的經驗,通過重寫或者是內部屬性的調整是完全可以使用UITableView/UICollectionView來達到這個效果,畢竟UITableView/UICollectionView是UIScrollView的子類,功能不會減少,而會更加強大,并且我們還能利用已有的data source和delegate機制,實現設計上的解耦。
其他常見的還有UINavigationBar、UITabBar、UIToolBar等等;
2.合理添加/刪除動態View;
有些View是動態的,就是偶爾顯示,偶爾隱藏。這類View有兩種處理方式:增刪,或者顯示/隱藏。沒有標準的答案,個人更推薦增刪的處理方式,即在有需要的時候添加到對應的ContainerView上,在不需要的時候將其刪除。這樣即可以與懶加載結合在一起,而且也能避免兩個動態View的相互影響,比如TableFooterView,或者是錯誤加載View。但這并不是唯一的方式,假如這個動態View所在的View層級比較簡單,并且需要動畫進行動態展示,則使用顯示/隱藏也是不錯的處理方式。
2.3.2 通用控件;
每一個程序員都可以建立自己的代碼庫,同理,每一位移動開發程序員都可以建立自己的通用控件代碼庫。這個庫內的控件,可以是你自己寫的,也可以是優秀的第三方開源控件。建立控件庫,除了能夠避免重新造輪子,大大提高我們的開發效率,還有更為重要的一點:在運用、改造、重構中掌握接口設計解耦,甚至是架構的知識和經驗。
每個App的UI設計、交互、布局和配色往往千差萬別,但總脫離不出移動App這一范疇,也就決定了在某些通用的控件交互上會保持一致性,以讓用戶依據自己在移動應用上的使用經驗就能輕松快速上手使用,這就是App的移動性。所以通用控件的適用場景往往是很“通用”的。比如下拉刷新、加載更多、Tab Bar、提示Tips、加載錯誤重新加載等等。在新的App或者功能模塊上運用這些控件時,你就會思考怎么讓控件更加通用,即不影響舊的邏輯,又能夠適用新的需求,這對于做界面的架構設計是非常好的鍛煉。
2.3.3 合理運用VC在替代View組合復雜界面;
在界面開發過程中,我們常常會遇到復雜的界面,比如多頁界面、多種布局方式展示多業務的首頁等,但由于很大部分開發者已經對“一屏就是一個VC”這一初學者的習慣奉為教條,寫出一個龐然大View,再加上復雜的邏輯代碼,這一塊的代碼很可能就演變成了誰都不敢動的禁區。一個VC可以管理多個VC,所以合理的使用VC來替代View進行復雜界面組合,不僅能夠將復雜界面切分成更小的粒度,邏輯代碼也同步合理劃分,便于維護和重構;而依托VC的機制,還能View和數據的動態加載管理。
下一章中關于輕VC的討論是這一節知識的拓展。
3. ViewController
上一節關于View的章節已討論了iOS界面機制,這一節則主要是來談談在寫界面過程中的設計問題和基本規范;
ViewController在iOS只是一個非常重要的概念,它是我們在開發界面時最常打交道的模塊,其在一個App中所扮演的角色,View Controller Programming Guide for iOS 中有清晰準確的描述:
- View Management:管理View;
- Data Marshalling:管理數據;
- ?User Interactions:響應用戶交互;
- Resource Management:管理資源;
- ?Adaptivity:適配不同的屏幕尺寸空間的變化;
可以看到,ViewController有太多的事情要做,這也就導致了ViewController非常容易變得代碼膨脹、邏輯混亂等問題;依照個人經驗,一個ViewController類的有效代碼超過500行,這個ViewController就會變得難以維護,但實際上在開發過程中,往往會遇到上1K行,甚至2~3K行的ViewController類;當一個ViewController類達到2~3K行,就意味著其他開發者接手這個模塊來修改東西,已經無法通過滾動來定位代碼,只能通過搜索;
所以,在進行界面開發時,ViewController需要特別注意模塊設計,將不同的模塊按照邏輯進行一定的拆分,即解耦,又防止ViewController模塊的代碼膨脹。這就是輕VC的理念;
3.1 輕VC
輕VC是前兩年非?;鸬拿~,現在似乎已經成為了一種業界規范或者是慣例。同上所述,一個VC的類,如果有效代碼超過了500行,則表示這個類看是變得臃腫而難以維護;到達800行,只能通過搜索來定位代碼時,重構已勢在必行;
關于輕VC,objc.io的開篇第一章#Issue 1 : Lighter View Controllers,足見這一理念的重要性。掌握輕VC的理念基本上是一個iOS開發者從初級邁向高級必備技能。#Issue 1 : Lighter View Controllers 文中介紹了構建輕VC幾種常見的方式:
- 將數據源等復雜接口從VC中剝離;
- 把業務邏輯代碼抽象到Model層;
- 將復雜View抽象成獨立的類;
- 使用VC的Containment的特點,將一個VC中邏輯分離的界面模塊剝離成為多個子VC;
想要設計出合理而易于理解和維護的輕VC結構,需要掌握輕VC的知識并有一定實踐經驗。在以下情況下,可以考慮將一個VC設計或者重構成更多模塊更多類的輕VC結構:
- 如上所述,代碼超過500行時;
- VC內的View的數據源來自多個不同的地方;
- VC內有多個復雜的View,需要展示數據實體類較為復雜;
總之,當你感覺你的VC已經變得臃腫,那么就可嘗試輕VC的實踐,實踐才有收獲。
3.2 VC的設計
相對于View關注于布局和展示,VC更關注設計和管理。本節以一個實例,來簡單介紹在一個完整App中的VC設計。
先來看一個常見的UI結構設計例子:
這個圖應該非常容易理解:最底部是一個側滑抽屜控件,該抽屜包含了App內容展示的TabBarController和設置的VC。
TabBarController的子Item VC包含了相應業務的List VC,點擊List VC進入到詳情View內;有些詳情VC是使用WebViewController來進行內容的展示。非常簡單,不是么?接下來說明該設計的洞見:
- Root ViewController,是整個App內Window的根VC,這是一個生命周期與App相同的VC,即Window的RootViewController是唯一且一直存在的,需要切換場景則使用這個Root VC控制子VC切換來實現(常見于場景:需要進行強登錄,即登錄之后才能使用的App,登錄成功后從登錄界面切換到主界面,則登錄VC和主界面VC都應該是Root VC的子VC,受Root VC的控制來進行切換)。這個RootViewController建議是一個UINavigationController,以此保證足夠擴展性,并提供更為豐富的界面交互選擇。這個Root VC的生命周期與App一致,這樣一些突發的靈活分支界面可以很好的展示在Root VC上,如全局的Loading提示、OpenURL的分支調整等;
- Main ViewController:主界面,是主要業務展示界面的根界面。該VC與RootVC功能上會很容易重合在一起,但需要注意的是,該VC并非一直存在,但切換到一些特定分支時,該VC會從Root VC上remove掉,比如前面所說的強登錄App,登錄界面與主界面就會需要進行切換。另外,該VC隔離了主要業務展示界面的VC與Root VC,便于App整體界面風格的改版和重構。比如現在上圖展示的是一個側滑抽屜+TabBar的組合,那到下個版本改版把側滑抽屜去掉,那么只需要使用TabBar替換DrawerMenu VC在Main VC中的位置即可,而不會影響到RootVC中其他分支展示出來的界面(如Push等)。
- TabBarItem ViewController:作為TabBar Controller的子Item VC,通常會設計為NavigationController,用以管理各TabBarItem內的VC棧。 注:如果需要在Push進入二級界面(Detail VC)時隱藏TabBar,只需要設置二級VC的>hidesBottomBarWhenPushed = true即可,如果想更加靈活的控制TabBar,例如進到三級頁面的時候顯示出TabBar(這個場景應該很少見),或者你的TabBar是自定義的,可以參考我寫的一個開源控件MZNavTab;
本節所示例的UI結構是一個非常通用的UI結構,市面上除游戲外60%以上的App都是類似的UI交互(統計來源于個人手機),假如你的UI交互與此類似而你的UI結構很混亂的話,不如嘗試下這個UI結構設計。
4. MVC、MVP、MVVM
MVC:
MVP:
MVVM:
圖注: 虛線箭頭:表示兩者之間是非強依賴關系。如MVC圖,View與Model一般沒有直接聯系。
虛線矩形:表示該模塊在對應架構設計中的隱性存在。即一般性架構中并沒有這個角色,但立足于iOS這個平臺,這又是不可或缺的一部分;
本文并不打算將MVC、MVP、MVVM這個幾個通用架構設計模式的概念統統在這里敘述一遍,上面三個圖基本上能夠很明白地對比出三者之間的差異。也許與你在網上看到的不盡相同,這是因為以上三圖更立足于iOS平臺。
4.1 MVC
我們最初看到的MVC設計模式圖可能是這樣的:
引自[MSDN#ASP.NET – Single-Page Applications: Build Modern, Responsive Web Apps with ASP.NET
而蘋果官方給的MVC的設計模式圖卻是這樣的:
到底哪一副圖才是真正的MVC?我的答案只能是:都是。
MVC從施樂帕克實驗室提出至今,已經應用到各種應用開發領域中:Web App可以用MVC,iOS/Android/Windows客戶端應用也用MVC,Web前端也在用MVC,等等;這些幾乎涵蓋了我們常見的開發領域,所以MVC其實已經超越了他原本最初的設計,基于所有涉及展示的應用都能套上MVC,只不過不同的平臺在設計上略有差別。而MVP和MVVM,也不過是MVC的衍生變種,除這兩者之外,還有我們沒怎么見過的HMVC、MVA等。
4.2 Model Layer
在討論MVP和MVVM之前,我想先明確一個經常被誤解的概念:Model。由于Model這個詞太通用化,如數據Model,數據庫Model,這就導致了Model這一概念理解差異化,簡單的說,就是被玩壞。拋開其他,我們來看看常見的定義:
Wikipedia的定義:
>The central component of MVC, the model, captures the behavior of the application in terms of its problem domain, independent of the user interface.[11] The model directly manages the data, logic and rules of the application.
MSDN(https://msdn.microsoft.com/en-us/library/ff649643.aspx)中的定義:
>Model. The model manages the behavior and data of the application domain, responds to requests for information about its state (usually from the view), and responds to instructions to change state (usually from the controller).
上面兩個定義基本一致:Model,管理應用的行為和數據。
再來看看Apple官方文檔Model-View-Controller的定義:
Model objects encapsulate the data specific to an application and define the logic and computation that manipulate and process that data. For example, a model object might represent a character in a game or a contact in an address book. A model object can have to-one and to-many relationships with other model objects, and so sometimes the model layer of an application effectively is one or more object graphs. Much of the data that is part of the persistent state of the application (whether that persistent state is stored in files or databases) should reside in the model objects after the data is loaded into the application. Because model objects represent knowledge and expertise related to a specific problem domain, they can be reused in similar problem domains. Ideally, a model object should have no explicit connection to the view objects that present its data and allow users to edit that data—it should not be concerned with user-interface and presentation issues.
Communication: User actions in the view layer that create or modify data are communicated through a controller object and result in the creation or updating of a model object. When a model object changes (for example, new data is received over a network connection), it notifies a controller object, which updates the appropriate view objects.
雖然Apple的官方文檔是定義Model Objects,但它的含義還是封裝數據以及管理數據相關的邏輯計算;
所以這里需要明確的一個概念是:在MVC的設計模式中,Model是一個Layer,而不只是一個數據模型(Data Model)類??傮w來說,Model Layer 包含了數據模型,以及管理這些數據相關的邏輯計算,如本地數據變化、數據緩存、從網絡請求數據等業務邏輯。關于這個問題,還可以參考這篇文章:《iOS應用架構談 view層的組織和調用方案》。但有一點需要說明:該文章更傾向于從Model Object上思考Model的定義,因為里面的關于Model的示例是從數據模型中擴展出業務接口;而本人則更傾向于從Model Layer來思考Model,即Model并不限于數據模型,可以是數據管理類(各種Manager)、請求隊列管理等等。
4.3 MVP VS MVVM
上一節關于Model Layer中推薦的文章《iOS應用架構談 view層的組織和調用方案》對MVC和MVVM都做了非常詳細的討論,是一篇非常不錯的文章,推薦各位閱讀,那么本節就來說說MVP,以及我為什么更傾向于選擇MVP作為App架構設計中的設計框架。
回顧下在本章一開始祭出的MVP以及MVVM兩張圖,兩者之間有什么不同?
MVVM的VM(View Model)到V(View),比MVP的P(Presenter)到V(View),多了數據綁定。也就是
MVP:是MVC的變種,其中Model和View的定義與MVC的一致,不同點在于:MVC的Controller是管理一組Model與View之間交互邏輯,是一個管理者;而Presenter(展示者)則是Model于View之間的連接者,針對特定模塊的View提供對應的格式化的Model數據,將View中的行為反饋到Model中。所以MVC中的Controller一般會管理一個或多個Model和一個或多個View,而Presenter則是 M-P-V 一對一,有更細的粒度和更好的解耦。
從MVP的定義,你會發現MVP與MVVM極其相似,Presenter與View Model扮演的角色基本沒有差別,除了前面所說到綁定機制。但綁定機制既有很明顯的強大優點——自動連接View和Model,也有很明顯的缺點——更高的耦合度,更復雜的代碼邏輯;但讓人感嘆命運無常的是:MVVM隨著ReativeCocoa而在iOS平臺炙手可熱,而iOS平臺上甚少有人提及的MVP,在Android平臺卻幾乎成了標準(Android5.0引入了數據綁定支持,MVVM會在Android平臺有新的發展)。
我為什么傾向于MVP?不過是相比于MVVM雙向綁定的便利,我更希望我的App設計中有更強的靈活性和擴展性。沒有完美的架構設計模式,只有適用于你的App業務場景和團隊的設計模式。比如數據邏輯并不復雜、更注重視覺展示的應用,原始的MVC往往是最優解。所有的MVC衍生出的變種,無非是為了Solve The Problem。
4.4 架構設計模式應用
無論MVC、MVP還是MVVM,都是指導我們進行架構設計的模式,并非可以生搬硬套的;而且在實際的應用中,對于這些設計模式總會有不同的理解,并且需要根據項目需求進行必要的調整;更為重要的是在我們App的架構設計中,處理好Model-View-Controller之間的關系只是基礎,最主要的挑戰來自于復雜的業務邏輯和場景,這才是體現一個架構師能力所在。
唐巧前不久寫的一篇文章《被誤解的MVC和被神化的MVVM》對MVC和MVVM的實踐的討論應該是體現了現在移動端主流架構思想,其中對>網絡請求層、ViewModel 層、Service 層、Storage 層等其它類的提取設計,才決定了一個App架構設計的優劣。
對于架構設計,我準備在下一篇文章,結合本人在iOS/Android兩端的設計經驗,做個深入的討論,并給出自己的設計范例,供各位討論參考。這里先拋出幾個在架構設計中最常思考的點,作為下一篇文章的引子:
- 架構是為了解耦,越松的耦合就代表越多的份層,但人的思維總是更愿意接受直線思維,怎么解決這個矛盾?
- 在一個App中,統一(一致)的架構設計能夠讓邏輯代碼更健壯,更有利于團隊成員間的溝通和項目維護,但如何解決其和靈活性之間的矛盾?
- 架構設計是否只包含邏輯分層?需要設計數據流和多線程么?
- 設計模式中的幾大原則;
5.總結
以上四個章節,先從UI整體出發,到剖析UIView幾點重要機制,接著討論怎么用好VC這個UI中重要的管理角色,最后則漫談了MVC/MVVM/MVP幾個架構設計模式的異同和實踐應用,想通過以點帶面,讓我們在關注了具體實現之后,能夠脫離出來,從俯視下我們App開發更為整體核心的部分。
版權:人人都是產品經理遵循行業規范,任何轉載的稿件都會明確標注作者和來源,若該文涉及版權問題,請聯系主編QQ:419297645
技術控