標籤:
本文基於資料字典和資料流圖兩種工具講述一個完整微部落格戶端的實現。資料字典和資料流圖都可以用來表達線程的執行流程,同時定義了需要的類,是進一步設計類的基礎。
資料字典實際上是一張表,表的第一個欄位是程式碼中的標識符,其它欄位具體描述它線上程中被如何使用,以及它所依賴的其它元素,資料字典中各個標識符基本上也是按照線程的執行流程來排序。
資料流圖是一個平面拓撲結構,每個節點或者是外部資料,或者是可被線程執行的代碼模組。從外部資料到代碼模組的邊意味著線程在執行代碼模組的時候需要用到外部資料,從代碼模組到代碼模組的邊則表示線程執行完成一個代碼模組後跳轉到另一個代碼模組開始執行。其它類型的邊沒有具體含義。
資料字典
· 線程啟動,執行函數main。
· int main(int argc, char *argv[])
—— 線程首先跳轉到函數main所在的代碼塊,然後可以跳轉到函數UIApplicationMain。
· int UIApplicationMain (
int argc,
char *argv[],
NSString *principalClassName,
NSString *delegateClassName
);
—— 線程調轉到函數UIApplicationMain所在的代碼塊,然後在記憶體中建立兩個分別引用了應用本身和應用代理的記憶體塊,其實就是UIApplication類(子類)和SAAppDelegate類(子類)的執行個體;然後調轉到 app delegate 執行個體,執行 applicationDidFinishLaunching 方法中定義的代碼;然後線程跳轉到UIApplication的執行個體,根據執行個體中的欄位和類中定義的代碼,進入等待接收事件的狀態;如果線程接收到介面控制項點擊事件,就跳轉到引用了這個控制項的記憶體塊(控制項對象),根據記憶體塊中的欄位值和控制項類中定義的代碼執行相應的過程,最後重新等待其它事件;如果線程接收到使用者終止了進程的事件,就跳轉到 app delegate 執行個體,執行 applicationWillTerminate 中的代碼,然後再跳轉到main函數,執行 return 語句終止自己。
· UIApplication
—— 類UIApplication以及它在記憶體中的執行個體中定義的代碼和資料, 可以告訴線程應該如何修改和獲得與應用程式相關的資訊,如何進入事件迴圈,線程等待各種事件,跳轉到相應的代碼位置。
· SAAppDelegate
—— 類SAAppDelegate以及它在記憶體中的執行個體中定義的代碼和資料,可以告訴線程如何處理與應用程式相關的事件,如何擷取資料模型等等。
· applicationDidFinishLaunching
—— 線程從UIApplication類或執行個體中的代碼跳轉到這個函數中,然後在記憶體中建立一個UIWindow類的執行個體,這個執行個體可以引用一個可以承載可視化元素的視窗,然後線程在記憶體建立一個控制器類SAMainController或SAOAuthController或SANewfeatureController類的執行個體,在把UIView的執行個體建立到記憶體後,調用 viewDidLoad 方法配置 view 對象中的各個欄位。然後跳轉到UIWindow類的代碼中,設定記憶體執行個體的欄位值,並把這個ViewController的執行個體作為視窗的根項目,然後跳轉到 makeKeyAndVisible的代碼中,根據根項目執行個體包含的UIView執行個體,畫出視窗中的介面元素,期間會跳轉到控制器執行個體的 viewWilAppear 等方法,執行完成後跳回UIApplication執行個體,進入等待事件的狀態。
資料流圖(順序圖)
ps:
關於為什麼要調用 performSelectorOnMainThread 才能更新介面: 因為程式員無法直接調用繪圖函數,如果讓程式員建立的線程來更改控制項對象,那麼就僅僅是改變了記憶體中某個執行個體的欄位值,主線程卻沒有收到介面更新的事件,仍然處於阻塞狀態,介面就不會更新。問題在於主線程是否會在下一次事件迴圈結束後更新介面。
iOS開發實踐:一個類微部落格戶端從啟動到與使用者互動的過程