先上圖:html
功能:ios
一、瀏覽商品,購買商品,支付;服務器
二、切換商店、查看訂單、訂單投訴、意見反饋;網絡
三、登錄、收貨地址管理;session
四、app首次啓動的初始化界面;閉包
架構上:架構
箭頭的指關係 表明着 直接調用,也表明着持有引用的意思。app
全部的實例均可以經過監聽event,達到交流的效果。框架
其中Model是單例,Controller 是storyBoard 上實例,view是Controller運行時加載並初始化;異步
Message是工廠模式,每個協議都實例化一個對象來解決;
Event經過封裝NSNotifycation實現。
網絡通信是經過Message調用AFNetworking。
設計中遇到的問題:
1,網絡層請求的封裝。一開始的作法是定義一個server類來處理請求,頭文件中定義請求的類型,全部的網絡請求都走server類,server類直接調用AFNetworking.
大體的形式以下:
Server:NSObject
{
-(void) requestLogin;
-(void) requestLogout;
....
}
這樣的好處是直接調用,開發方便,邏輯也比較簡單。
壞處是,全部的代碼都寫在一塊兒,不方便維護,同時很差作統一的邏輯處理(好比說session過時等)。
如今採用的作法:
定義一個BaseMessage,封裝AFNetworking的調用,還有統一的邏輯處理。
同時定義OrderMessage,CartMessage,GoodsMessage,ShopMessage等繼承BaseMessage,來具體實現特定的邏輯。
這樣作的好處,把邏輯分類,代碼按照模塊分散到每一個SubMessage,方便維護。
還能夠優化的地方:
如今的請求是一個Message就是一個網絡請求(http),處理完以後要在Message拋出事件,來通知其餘模塊的信息。而且,每一個Message都是相互獨立的,並無統一調度的過程。
能夠新建一個MessageQueue類,來存放全部的Message請求,經過MessageQueue來調度http請求。
這樣的涉及到的問題是:結果回來後,如何通知其餘對象?
作法1:
當請求Message的時候,self實現一個接口,而且傳入self;回調的時候,直接經過接口調用;
作法2:
請求的時候,帶一個閉包參數,回調的時候直接調用閉包;
作法3:
請求以後監聽事件;回調時經過事件響應;
比較理想的作法:
有controller 、 message 、msgCenter三個實例。
controller監聽事件,發送message;
message實現接口,本身把本身添加進msgCenter隊列;
msgcenter對BaseMessage進行處理,經過接口來查詢message 裏ID等詳細信息;回調後,經過調用message的接口。
controller 和 message 用的是監聽者模式;
msgCenter 和 message 之間用的是代理模式;
msgCenter 能夠實現異步的與服務器交互,和對message 的統一處理。
( http://www.cnblogs.com/loying/p/4804566.html 參考自 蘑菇街的IM 網絡層)
2,MVC框架的實現。ios的設計,自己就含有不少MVC的思想,好比說要實現一個自定義UITableView,就要繼承UITableView,自定義delegate,與Controller的交流 是經過delegate實現。同時,一個頁面就是一個controller,也要繼承UIViewController。
天然而然地,在寫代碼的時候就會M(model)、V(View)、C(controller)的區分。
但在實際的需求中,遇到一些正常的需求的時候,若是沒有設計好,也會很棘手。
好比說:首頁下方的購物車模塊、商品展現的模塊,這些都是須要重複出現的模塊,也就是須要重用的模塊。如何設計購物車模塊,使得購物車模塊 和 持有購物車的模塊(首頁、子類目等)之間沒有耦合,也是一個麻煩的事情。
具體的需求有幾個:
一、購物車點開的時候,頁面除購物車的背景要灰掉,同時購車要有上滑的動畫;
二、點擊購物車或者點擊背景的時候,購物車彈下,同時灰色背景去除;
三、購物車中點擊商品的增減,要實時反饋到頁面上(首頁、子類目等);
四、購物車點開以後的大小,由購物車內的物品決定,有最大高度;
五、購物車的物品減到0的時候,不消除;
....
controller與view之間的交互,controller持有view,能夠 直接調用view;view要調用controller或者其餘view,能夠經過事件、委託等方式;
不論是事件仍是委託,爲的是解耦,讓view與controller之間不耦合,因此切記不可在view定義一個controller的屬性,而後傳遞controller進來。
解決方案:
view 與 controller 之間用委託(記得@property(weak),不然循環引用,內存沒法釋放);
view 與 view 之間用事件機制;
在interface builder能夠用outlet 來作委託機制,很是方便,具體的流程和UITableView相似;
3,事件機制
沒有用第三方的事件機制(如EventBus等),用的是NSNotifycation來實現;
一開始的作法是:
#define NOTIFY_SERVER_USER_LOGIN @"NOTIFY_SERVER_USER_LOGIN"
#define NOTIFY_UI_REQUEST_PHONE_CALL @"NOTIFY_UI_REQUEST_PHONE_CALL"
直接define具體的協議,若是帶有數據,就存到notify的userInfo;
這樣在代碼寫了比較多時候,當改動一個notify的userInfo的時候,常常會忘記改其餘的某處,並且每每記不得userInfo裏面的數據格式,不便於維護;
因而在NSNotify的基礎上作了一層封裝:
定義一個BaseEvent,負責把event的類型轉成nsnotify(類型名字@"",屬性轉成dict),同時把nsnotify轉成event;
同時Event分紅幾類ErrorEvent ServerEvent UIEvent DataEvent等。
好比:
@interface UIMessageConfirmEvent : BaseEvent
@property (nonatomic , copy) NSString* message;
@end
發送事件的時候,能夠直接在event類型裏面給message賦值;
開發中的幾個原則:
1,不要有很大的文件,除非不多改動;(大文件,不方便維護和開發)
2,一個函數儘可能只作一個功能,若是有多個地方調用,要保證調用的意義是相同的;(儘可能不要在調用參數中帶默認參數,或者在複雜調用中帶flag來標示此次調用的含義)
3,調用時的參數檢查,通常由被調用的函數檢查參數;若是涉及到參數不對時,須要有相應的邏輯操做,好比彈出提示框等的,儘可能由調用者來檢查參數;