轉自:http://www.cocoachina.com/bbs/read.php?tid-73476-keyword-%CE%A2%B2%A9.html
一、組成和關係
該架構除了由大量的諸如資料連線、資料模型等基礎類支撐外,其主要的功能由 RootViewControllerComposeViewController、OAuthcontroller、OAuthEngine URLConnection、WeiboClient 6個類完成,RootViewController是整個架構的視圖控制器,它作為應用程式委託中的UINavigationController類型的輸出口,控制該系統的主視圖以呈現給使用者。ComposeViewController類是作為RootViewController類的組成部分存在的,用以控制寫微博時所呈現出的發送視圖。OAuthcontrller用以控制完成OAuth認證機制所需要的視圖。類OAuthEngine、URLConnection、WeiboClient為服務類,為各視圖控制類提供服務,類OAuthEngine為完成OAuth方式認證提供了支援,通過該方法完成授權和認證過程,URLConncetion和WeiboClient建立網路連接,實現新浪提供的OPEN
API功能,設定並完成HTTP請求以發送和接受資料。
二、各類簡單說明
1、RootViewController類
該類是整個系統的視圖控制類,是系統與外面互動的入口,也是系統的啟動並執行驅動點,它關聯了OAuthEngine等服務類,在該類通過調用其他各服務類提供的功能,完成從使用者的登入授權認證到把
微博客。在viewDidLoad方法中,完成了對用於儲存
微博列表的NSMutableArray類的status的初如化。接著在viewDidAppear方法中,用服務方提供的三個URL和應用程式在新浪方擷取的Key和Secret完成其成員OAuthEngine類型的_engine的初始化工作,為OAuth認證提供了準備。在此之類,就調用自身loadTimeline方法,來完成包括OAuth認證、請求資料等一系列動作,從此,系統啟動並執行萬裡長征正式踏上征程。
2、ComposeViewController類
該類所控制的視圖是RootViewController類所控制的視圖的組成一部分,當使用者點擊主視圖上面導覽列中的發送按鈕,該類所控制的視圖將呈現出來,主要用於發送微博。Draft類描述發送微博時的附件資訊,newTweet方法的主要作用是初始化draft,為發送新的微博上傳相關附件提供對應的對象,send方法用於調用的OPENG
API完成發送這一動作,insert方法在發送微博時插入附件時被調用。
3、OAuthController類該類主要用於調用OAuthEngine類的服務來完成OAuth認證機制中的認證工作的三步認證,它由RootViewController類中的loodTimeline方法調用。該類中的_webView成員是用來顯示使用者授權介面的UIVebView控制項,因此就實現了UIWebViewDelegate委託,用委託中相應的方法協調完成認證過程。該控制項的URLRequest屬性被設定為三步認證中的第二個URL,用於擷取使用者授權的Request Token。
4、OAuthEngine類該類是OAuth認證實現的核心類,為其他類提供認證服務。調用requestRequestToken將擷取到經過授權的擷取使用者授權的Request Token,調用requestAccessToken將用授權的Request Token換取Access Token。
5、URLConnection和WeiboClient類WeiboClient是URLConnection的子類,WeiboClient實現了OPEN API方法,設定並完成HTTP請求以發送和接受資料,並用指定的action來處理通過的HTTP請求得到資料。
二、進入使用者授權介面的步驟
系統運行後,經過RootViewController類的viewDidApper事件方法,調用其lodadTimeline方法完成OAuth認證機制的第一步(擷取未授權的Request Token),之後進入到OAuthController類的loadView方法,該方法中通過語句:“*request = _engine.authorizeURLRequest; [_webView
loadRequest: request];”完成認證機制中第二步,接著進入到webViewDidFinshg
事件方法,進入到授權介面。具體細節比較複雜,見下面的(進入授權介面的時序圖),由於沒有專門的UML工具,加之涉及到的對象較多,時序圖沒有列出所有的對象和細節。在進入RootViewController的viewDidAppear事件方法中,判斷該類中的_engine是否已經存在,如果沒有就對其初始化,接著調用“[self performSelector:@selector(loadTimeline) withObject:nil afterDelay:0.0]; ”進入到loadTimeline方法中。loadTimeline方法首先用本類中的執行個體成員_engine作為參數,著手構建OAuthController對象,下一步就判斷剛剛構建的動作是否真的構建了對象,如果對象存在,就立即轉入到剛剛構建OAuthController類對象所對應的視圖,即進入到授權介面,以供使用者進行授權。如果不存在OAuthController對象,就說明已經完成了認證,不用進入到授權介面,直接調用loadData載入與授權使用者相關的微博資訊後,進入到RootViewController對應視圖即可。其中建立OAuthController對象是關鍵,在其中進行了判斷,如果已經授權了或者cache中還儲存著相應的cooke的話,就退出,否則就用_engine為參數,調用OAuthController的初始化方法,初始化後又判斷_engine.OAuthSetup
的值,如果為NO則表示還沒有進行過認證(若為YES則表示已經完成了認證步中的第一步),於是就調用¬¬¬¬_engine requestRequestToken來完成認證的第一步操作。OAuthEngine類中requestRequestToken方法的調用過程:該方法是一中間方法,起到過渡作用,它只是調用 requestURL: token:onSuccess: onFai:方法,後一個方法用指定的URL和兩個方法SEL作為參數,其中兩個SEL分別用於當該HTTP請求成功或失敗返回時對應的處理方法。它分別指定為setRequestToken和outhTicketFailed方法。
OAuthEngine類中的requestURL:token:onSuccess:onFail方法又用給定的URL和token構建了OAMutableURLRequest對象,然後構建OADataFetcher對象,並把它來提取基於OAMutableURLRequest網路連接的資料(調用onSucess:和onFail方法)。如果成功,就調用上面傳過來的OAuthEngine類中setRequestToken方法處理認證第一步的返回資料。setRequestToken只是用得到的資料填充用OAuthEngine類中的_requestToken。
至此,已經完成了構建OAuthController對象,並工作完成了OAuth認證中的第一步了。接著,程式一路回退,回退至loadTimeline
方法中:
UIViewController *controller = [OAuthController controllerToEnterCredentialsWithEngine: _engine delegate:self]//通過以上的過程,該句已經執行完畢
if(controller)//第一次進入時總需要認證,總會構建controller,所以為為真值
[self presentModalViewContrllor: controller animated:YES];//
else
[self loadData];由於presentModalViewContrllor是非同步方法呼叫,調用後,loadTimeline就當即結束了。經過幾番系統 的“原子操作後”,進入到OAuthController類中的loadView 事件方法中,在該事件方法中,將完成OAuth認證機制中的第二步過程。該方法對即將出現的授權介面中的一些UI進行了初始化設定後,調用:
NSURLRequest *request = _engine.authorizeURLRequest;
[_webView loadRequest:request];
在OAuthEngine類的authorizeURLRequest方法中,首先判斷_requestToke.key是否為空白(由於我在第一步的認證過程上,已經設定好了),若不為空白,則用authorizeURL和_requestToken等為參數,構建OAMutableURLRequest對象,並基於此設定好相關的HTTP請求,並返回供_webView載入,loadView結束後再進入_webViewDidFinishLoad事件方法。
至此,授權介面已經出現,以供使用者對其授權,介面如下:
此過程的詳細調用情況見:
接上:進入授權介面的時序圖三、使用者授權後並進入到微博主介面的調用關係
當使用者在授權介面上填寫好帳號和密碼後,點擊“授權”後,觸發OAuthController類的webViewStartLoadWithRequest事件和webViewDidFinishLoad方法,在webViewDidFinishLoad中調用gotPin方法得到Access Token完成OAuth認證機制的最後一步。之後RootViewController類中的viewDidAppear事件方法被觸發,在該方法中,調用loadData方法,完成資料的載入工作,然後就顯示了微博的主列表介面。
具體細節比較複雜,見下面的(進入授權介面的時序圖),由於沒有專門的UML工具,加之涉及到的對象較多,時序圖沒有列出所有的對象和細節。該時序圖僅描述使用者授權過程(即OAuth認證的最後步),沒有描述認證後其中載入資料的詳細過程,詳細過程見方法調用圖。
幾個重要方法:
RootViewController類中loadTimeline方法:該方法是本架構中的一個主要中轉方法,此方法調用OAuthController類的controllerToEnterCredentialsWithEng
ine完成認證中的前兩步操作,調用loadData方法完成認證的第三步和載入資料過程。
OAuthEngine類中的requestRequestToken方法用來完成認證第步的請求,setRequestToken方法用來處理接收資料,並設定好_requestToken;requestAccessToken方法用來完成認證第三步,setAccessToken方法用來處理上步接收的資料,並設定_accessToken
從而完成整個認證操作。OAuthController類中的locateAuthPinInW
ebView方法用來從返回的HTTP請求中擷取數字 PIN 碼,即擷取用授權的Request Token,完成認證的第二步,用此來作為第三步的參數。
RootViewController類中的timelineDidReceiveForComment方法用來處理接收從HTTP請求返回中的資料,在此方法中實現微博的資料的還原序列化工作。
四、幾點發現
1、OAuthController類中的webViewDiFinishLoad事件方法中通過調用: _delegate OAuthController:self authenticatiedWit
ntroller:authenticatedWithUserName:_engine.username 方法間接地又調用了一次loadTimeline和loadData 方法產生WeiboCleint
對象並進行認證和載入資料操作,但由於WeiboClient對象是自動銷毀後,程式立即進入到了RootViewController類的viewDidApper事件方法,在這個方法中又調用loadTimeline,以至於上面的操作是多餘的,等於在進行了兩次認證(第二步和第三步)和載入資料操作。
2.關於OAuthController類中的webView:shouldStartLoadWit
hRequest事件方法(視圖類的相關事件方法也一樣)連續被調用多次問題。這是一個很有趣的問題,至今我沒有發現什麼原因。比如說要轉到(presentModalViewController:)一個視圖(該視圖實現了UIWebViewDelegate委託),該視圖控制器中實現了viewDidLoad和loadView事件方法,如果在這些方法中沒有調用其父類的對應方法,則被轉到的視圖控制器中的這兩個方法會串連地被調用,我一次實驗是連續地被調用了11次?但如果加上 super viewDidLoad 的話只正常地被調用1次。至於是什麼原因,我至今未懂。