天天看點

iOS:ASIHttpRequest雖不更新,但仍值得詳細了解

一、使用ASIHTTPRequest可以很友善的進行一下操作:同步/異步方式下載下傳資料,定義下載下傳隊列,讓隊列中的任務按指定的并發數來下載下傳(隊列下載下傳必須是異步的),送出表單,檔案上傳,處理cookie,設定代理,上下載下傳進度條,重定向處理,請求與響應的GZIP,驗證與授權。

使用ASIHTTPRequest可以很友善的進行一下操作:

同步/異步方式下載下傳資料

定義下載下傳隊列,讓隊列中的任務按指定的并發數來下載下傳(隊列下載下傳必須是異步的)

送出表單,檔案上傳

處理cookie

設定代理

上下載下傳進度條

重定向處理

請求與響應的GZIP

驗證與授權

等等,隻要跟HTTP有關,隻有你想不到的,沒有她做不到的~

配置方法:

ASIHTTPRequestConfig.h

ASIHTTPRequestDelegate.h

ASIProgressDelegate.h

ASICacheDelegate.h

ASIHTTPRequest.h

ASIHTTPRequest.m

ASIDataCompressor.h

ASIDataCompressor.m

ASIDataDecompressor.h

ASIDataDecompressor.m

ASIFormDataRequest.h

ASIInputStream.h

ASIInputStream.m

ASIFormDataRequest.m

ASINetworkQueue.h

ASINetworkQueue.m

ASIDownloadCache.h

ASIDownloadCache.m

iPhone 工程還需要:

ASIAuthenticationDialog.h

ASIAuthenticationDialog.m

Reachability.h (在External/Reachability 目錄下)

Reachability.m (在 External/Reachability 目錄下)

庫引用:

CFNetwork.framework

SystemConfiguration.framework

MobileCoreServices.framework

CoreGraphics.framework

和libz.dylib

另外,還需要libxml2.dylib(libxml2還需要設定連接配接選項-lxml2 和頭檔案搜尋路徑/usr/include/libxml2)

二、ASIHttpRequest建立和執行request

iOS開發中ASIHttpRequest如何建立和執行request,其中包括同步請求,異步請求,使用Block,使用隊列,取消異步請求等等内容。

建立NSOperationQueue,這個Cocoa架構的執行任務(NSOperation)的任務隊列。我們通過ASIHTTPRequest.h的源碼可以看到,此類本身就是一個NSOperation的子類。也就是說它可以直接被放到任務隊列中并被執行。

同步請求

同步請求會在目前線程中執行,使用error屬性來檢查結束狀态(要下載下傳大檔案,則需要設定downloadDestinationPath來儲存檔案到本地):

iOS:ASIHttpRequest雖不更新,但仍值得詳細了解
iOS:ASIHttpRequest雖不更新,但仍值得詳細了解

同步請求會阻塞主線程的執行,這導緻使用者界面不響應使用者操作,任何動畫都會停止渲染。

異步請求

下面是最簡單的異步請求方法,這個request會在全局的NSOperationQueue中執行,若要進行更複雜的操作,我們需要自己建立NSOperationQueue或者ASINetworkQueue,後面會講到。

iOS:ASIHttpRequest雖不更新,但仍值得詳細了解
iOS:ASIHttpRequest雖不更新,但仍值得詳細了解

使用block

在平台支援情況下,ASIHTTPRequest1.8以上支援block。

iOS:ASIHttpRequest雖不更新,但仍值得詳細了解
iOS:ASIHttpRequest雖不更新,但仍值得詳細了解

注意,聲明request時要使用__block修飾符,這是為了告訴block不要retain request,以免出現retain循環,因為request是會retain block的。

使用隊列

建立NSOperationQueue或者ASINetworkQueue隊列,我們還可以設定最大并發連接配接數:maxConcurrentOperationCount

iOS:ASIHttpRequest雖不更新,但仍值得詳細了解
iOS:ASIHttpRequest雖不更新,但仍值得詳細了解

如果不設定selector,那麼系統會使用預設的requestFinished: 和 requestFailed:方法

如果需要對隊列裡面的每個request進行區分,那麼可以設定request的userInfo屬性,它是個NSDictionary,或者更簡單的方法是設定每個request的tag屬性,這兩個屬性都不會被發送到伺服器。

不要使用request的URL來區分每個request,因為URL可能會改變(例如重定向),如果需要使用request的URL,使用[request originalURL],這個将永遠傳回第一個url。

對于ASINetworkQueue

ASINetworkQueue是NSOperationQueue的子類,提供更進階的特性(ASINetworkQueue的代理函數):

requestDidStartSelector

當一個request開始執行時,這個代理函數會被調用。

requestDidReceiveResponseHeadersSelector

當隊列中的request收到伺服器傳回的頭資訊時,這個代理函數會被調用。對于下載下傳很大的檔案,這個通常比整個request的完成要早。

requestDidFinishSelector

當每個request完成時,這個代理函數會被調用。

requestDidFailSelector

當每個request失敗時,這個代理函數會被調用。

queueDidFinishSelector

當隊列完成(無論request失敗還是成功)時,這個代理函數會被調用。

ASINetworkQueues與NSOperationQueues稍有不同,加入隊列的request不會立即開始執行。如果隊列打開了進度開關,那麼隊列開始時,會先對所有GET型request進行一次HEAD請求,獲得總下載下傳大小,然後真正的request才被執行。

向一個已經開始進行的ASINetworkQueue 加入request會怎樣?

如果你使用ASINetworkQueue來跟蹤若幹request的進度,隻有當新的request開始執行時,總進度才會進行自适應調整(向後移動)。ASINetworkQueue不會為隊列開始後才加入的request進行HEAD請求,是以如果你一次向一個正在執行的隊列加入很多request,那麼總進度不會立即被更新。

如果隊列已經開始了,不需要再次調用[queue go]。

當ASINetworkQueue中的一個request失敗時,預設情況下,ASINetworkQueue會取消所有其他的request。要禁用這個特性,設定 [queue setShouldCancelAllRequestsOnFailure:NO]。

ASINetworkQueues隻可以執行ASIHTTPRequest操作,二不可以用于通用操作。試圖加入一個不是ASIHTTPRequest的NSOperation将會導緻抛出錯誤。

取消異步請求

取消一個異步請求(無論request是由[request startAsynchronous]開始的還是從你建立的隊列中開始的),使用[request cancel]即可。注意同步請求不可以被取消。

注意,如果你取消了一個request,那麼這個request将會被視為請求失敗,并且request的代理或者隊列的代理的失敗代理函數将被調用。如果你不想讓代理函數被調用,那麼将delegate設定為nil,或者使用clearDelegatesAndCancel方法來取消request。

clearDelegatesAndCancel 将會首先清除所有的代理和block。

當使用ASINetworkQueue時,如果取消了隊列中的一個request,那麼隊列中其他所有request都會被取消,可以設定shouldCancelAllRequestsOnFailure的值為NO來避免這個現象。

安全地控制delegate防止request完成之前代理被釋放

request并不retain它們的代理,是以有可能你已經釋放了代理,而之後request完成了,這将會引起崩潰。大多數情況下,如果你的代理即将被釋放,你一定也希望取消所有request,因為你已經不再關心它們的傳回情況了。如此做:

iOS:ASIHttpRequest雖不更新,但仍值得詳細了解
iOS:ASIHttpRequest雖不更新,但仍值得詳細了解

三、ASIHttpRequest發送資料

ASIHttpRequest發送資料的内容,其中包括設定request頭,使用ASIFormDataRequest POST表單,PUT請求、自定義POST請求等等内容。

設定request頭

使用ASIFormDataRequest POST表單

通常資料是以’application/x-www-form-urlencoded’格式發送的,如果上傳了二進制資料或者檔案,那麼格式将自動變為‘multipart/form-data’ 。

檔案中的資料是需要時才從磁盤加載,是以隻要web server能處理,那麼上傳大檔案是沒有問題的。

資料的mime頭是自動判定的,但是如果你想自定義mime頭,那麼這樣:

iOS:ASIHttpRequest雖不更新,但仍值得詳細了解
iOS:ASIHttpRequest雖不更新,但仍值得詳細了解

你可以使用addPostValue方法來發送相同name的多個資料(夢維:服務端會以數組方式呈現):

PUT請求、自定義POST請求

如果你想發送PUT請求,或者你想自定義POST請求,使用appendPostData: 或者 appendPostDataFromFile:

四、ASIHTTPRequest進度追蹤

ASIHTTPRequest進度追蹤的内容,其中包括追蹤單個request的下載下傳進度,追蹤一系列request的下載下傳進度,追蹤單個request的上傳進度,追蹤一系列request的上傳進度,精确進度條vs簡單進度條,自定義進度追蹤等等内容。

每個ASIHTTPRequest有兩個delegate用來追蹤進度:

downloadProgressDelegate (下載下傳) 和 uploadProgressDelegate (上載)。

進度delegate可以是NSProgressIndicators (Mac OS X) 或者 UIProgressViews (iPhone).ASIHTTPRequest會自适應這兩個class的行為。你也可以使用自定義class作為進度delegate,隻要它響應setProgress:函數。

如果你執行單個request,那麼你需要為該request設定upload/download進度delegate

如果你在進行多個請求,并且你想要追蹤整個隊列中的進度,你必須使用ASINetworkQueue并設定隊列的進度delegate

如果上述兩者你想同時擁有,恭喜你,0.97版以後的ASIHTTPRequest,這個可以有 ^ ^

IMPORTANT:如果你向一個要求身份驗證的網站上傳資料,那麼每次授權失敗,上傳進度條就會被重置為上一次的進度值。是以,當與需要授權的web伺服器互動時,建議僅當useSessionPersistence為YES時才使用上傳進度條,并且確定你在追蹤大量資料的上傳進度之前,先使用另外的request來進行授權。 

追蹤小于128KB的資料上傳進度目前無法做到,而對于大于128kb的資料,進度delegate不會收到第一個128kb資料塊的進度資訊。這是因為CFNetwork庫API的限制。我們曾向apple送出過bug報告(bug id 6596016),希望apple能修改CFNetwork庫以便實作上述功能。

2009-6-21:Apple的哥們兒們真棒!iPhone 3.0 SDK裡,buffer大小已經被減小到32KB了,我們的上傳進度條可以更精确了。

<a></a>

這個例子中, myProgressIndicator是個 NSProgressIndicator.

在這個例子中, myProgressIndicator 是個 UIProgressView, myQueue是個 ASINetworkQueue.

iOS:ASIHttpRequest雖不更新,但仍值得詳細了解
iOS:ASIHttpRequest雖不更新,但仍值得詳細了解

這個例子中,我們已經為ASINetworkQueues調用過[myQueue go]了。

在這個例子中, myProgressIndicator 是個 UIProgressView。

iOS:ASIHttpRequest雖不更新,但仍值得詳細了解
iOS:ASIHttpRequest雖不更新,但仍值得詳細了解

這個例子中, myProgressIndicator是個 NSProgressIndicator, myQueue是個ASINetworkQueue.

iOS:ASIHttpRequest雖不更新,但仍值得詳細了解
iOS:ASIHttpRequest雖不更新,但仍值得詳細了解

ASIHTTPRequest提供兩種進度條顯示,簡單進度條和精确進度條,使用ASIHTTPRequests 和ASINetworkQueues的showAccurateProgress 來控制。為一個request設定showAccurateProgress隻會對該request有效。如果你為一個隊列設定showAccurateProgress,那麼會影響隊列裡所有的request。

當使用簡單進度條時,進度條隻會在一個request完成時才更新。對于單個request,這意味着你隻有兩個進度狀态:0%和100%。對于一個有5個request的隊列來說,有五個狀态:0%,25%,50%,75%,100%,每個request完成時,進度條增長一次。

簡單進度條(showAccurateProgress = NO)是ASINetworkQueue的預設值,适用于大量小資料請求。

當使用精确進度條時,每當位元組被上傳或下載下傳時,進度條都會更新。它适用于上傳/下載下傳大塊資料的請求,并且會更好的顯示已經發送/接收的資料量。

使用精确進度條追蹤上傳會輕微降低界面效率,因為進度delegate(一般是UIProgressViews 或NSProgressIndicators)會更頻繁地重繪。

使用精确進度條追蹤下載下傳會更影響界面效率,因為隊列會先為每個GET型request進行HEAD請求,以便統計總下載下傳量。強烈推薦對下載下傳大檔案的隊列使用精确進度條,但是要避免對大量小資料請求使用精确進度條。

精确進度條(showAccurateProgress = YES)是以同步方式執行的ASIHTTPRequest的預設值。

ASIProgressDelegate 協定定義了所有能更新一個request進度的方法。多數情況下,設定你的uploadProgressDelegate或者 downloadProgressDelegate為NSProgressIndicator或者UIProgressView會很好。但是,如果你想進行更複雜的追蹤,你的進度delegate實作下列函數要比 setProgress: (iOS) 或者 setDoubleValue: / setMaxValue: (Mac)好:

這些函數允許你在實際量的資料被上傳或下載下傳時更新進度,而非簡單方法的0到1之間的數字。

request:didReceiveBytes: 每次request下載下傳了更多資料時,這個函數會被調用(注意,這個函數與一般的代理實作的 request:didReceiveData:函數不同)。

request:incrementDownloadSizeBy: 當下載下傳的大小發生改變時,這個函數會被調用,傳入的參數是你需要增加的大小。這通常發生在request收到響應頭并且找到下載下傳大小時。

request:didSendBytes: 每次request可以發送更多資料時,這個函數會被調用。注意:當一個request需要消除上傳進度時(通常是該request發送了一段資料,但是因為授權失敗或者其他什麼原因導緻這段資料需要重發)這個函數會被傳入一個小于零的數字。

五、ASIHTTPRequest斷點續傳(下載下傳)

ASIHTTPRequest斷點續傳(下載下傳)的内容,其中包括ASIHTTPRequest可以恢複中斷的下載下傳,設定一個臨時下載下傳路徑,斷點續傳的工作原理等等内容。

從0.94版本開始,ASIHTTPRequest可以恢複中斷的下載下傳。

這個特性隻對下載下傳資料到檔案中有效,你必須為一下情況的request設定allowResumeForFileDownloads 為YES:

任何你希望将來可以斷點續傳的下載下傳(否則,ASIHTTPRequest會在取消或者釋放記憶體時将臨時檔案删除)

任何你要進行斷點續傳的下載下傳

另外,你必須自己設定一個臨時下載下傳路徑(setTemporaryFileDownloadPath),這個路徑是未完成的資料的路徑。新的資料将會被添加到這個檔案,當下載下傳完成時,這個檔案将被移動到downloadDestinationPath 。

iOS:ASIHttpRequest雖不更新,但仍值得詳細了解
iOS:ASIHttpRequest雖不更新,但仍值得詳細了解

斷點續傳的工作原理是讀取temporaryFileDownloadPath的檔案的大小,并使用Range: bytes=x HTTP頭來請求剩餘的檔案内容。

ASIHTTPRequest并不檢測是否存在Accept-Ranges頭(因為額外的HEAD頭請求會消耗額外的資源),是以隻有确定伺服器支援斷點續傳下載下傳時,再使用這個特性。

六、ASIHttpRequest請求HTTPS

iOS:ASIHttpRequest雖不更新,但仍值得詳細了解
iOS:ASIHttpRequest雖不更新,但仍值得詳細了解

程式猿神奇的手,每時每刻,這雙手都在改變着世界的互動方式!

本文轉自當天真遇到現實部落格園部落格,原文連結:http://www.cnblogs.com/XYQ-208910/p/5652576.html,如需轉載請自行聯系原作者

繼續閱讀