iPhone網絡開發之如何使用NSURLConnection

  1.  這篇文章是翻譯的蘋果官方文檔,想要看英文原版的可以到蘋果網站查看   
  2.   
  3. NSURLConnection 提供了很多靈活的方法下載URL內容   
  4. 也提供了一個簡單的接口去創建和放棄連接,同時使用很多的delegate   
  5. 方法去支持連接過程的反饋和控制   
  6.   
  7. 如何創建一個連接呢?   
  8.   
  9. 爲了下載url的內容,程序需要提供一個delegate對象,並且至少實現下面的方法   
  10. connection:didReceiveResponse:,conncetion:didReceiveData,   
  11. conncetion:didFailWithError:和connectionDidFinishLoading:   
  12.   
  13. 舉例一:   
  14. 1、先創建一個NSURL   
  15. 2、在通過NSURL創建NSURLRequest,可以指定緩存規則和超時時間   
  16. 3、創建NSURLConnection實例,指定NSURLRequest和一個delegate對象   
  17.    如果創建失敗,則會返回nil,如果創建成功則創建一個NSMutalbeData的實例用來存儲數據   
  18.   
  19. 代碼:   
  20. NSURLRequest *theRequest=[NSURLRequest requestWithURL:   
  21.                   [NSURL URLWithString:@“http://www.sina.com.cn/”]   
  22.                  cachePolicy:NSURLRequestUseProtocolCachePolicy   
  23.                  timeoutInterval:60.0];   
  24. NSURLConnection *theConncetion=[[NSURLConnection alloc]        
  25.                    initWithRequest:theRequest delegate:self];   
  26. if(theConnection)   
  27. {   
  28. //創建NSMutableData   
  29.   receivedData=[[NSMutableData data] retain];   
  30. else 創建失敗   
  31.   
  32. NSURLConnection還有幾個初始化函數,有個初始化函數可以做到創建連接但是並   
  33. 不馬上開始下載,而是通過start:開始   
  34.   
  35. 當收到initWithRequest: delegate: 消息時,下載會立即開始,在代理(delegate)   
  36. 收到connectionDidFinishLoading:或者connection:didFailWithError:消息之前   
  37. 可以通過給連接發送一個cancel:消息來中斷下載   
  38.   
  39. 當服務器提供了足夠客戶程序創建NSURLResponse對象的信息時,代理對象會收到   
  40. 一個connection:didReceiveResponse:消息,在消息內可以檢查NSURLResponse   
  41. 對象和確定數據的預期長途,mime類型,文件名以及其他服務器提供的元信息   
  42.   
  43. 要注意,一個簡單的連接也可能會收到多個connection:didReceiveResponse:消息   
  44. 當服務器連接重置或者一些罕見的原因(比如多組mime文檔),代理都會收到該消息   
  45. 這時候應該重置進度指示,丟棄之前接收的數據   
  46.   
  47. -(void)connection:(NSURLConnection *)connectiondidReceiveResponse:   
  48.                         (NSURLResponse*)response   
  49. {   
  50.   
  51.    [receiveData setLength:0];   
  52.   
  53. }   
  54.   
  55. 當下載開始的時候,每當有數據接收,代理會定期收到connection:didReceiveData:消息   
  56. 代理應當在實現中儲存新接收的數據,下面的例子既是如此   
  57.   
  58. -(void) connection:(NSURLConnection*)connection didReceiveData:   
  59.             (NSData *) data   
  60. {   
  61.    [receiveData appendData:data];   
  62.   
  63. }   
  64. 在上面的方法實現中,可以加入一個進度指示器,提示用戶下載進度   
  65.   
  66. 當下載的過程中有錯誤發生的時候,代理會收到一個connection:didFailWithError消息   
  67. 消息參數裏面的NSError對象提供了具體的錯誤細節,它也能提供在用戶信息字典裏面失敗的   
  68. url請求(使用NSErrorFailingURLStringKey)   
  69.   
  70. 當代理接收到連接的connection:didFailWithError消息後,對於該連接不會在收到任何消息   
  71.   
  72. 舉例   
  73. -(void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error   
  74. {   
  75. [connection release];   
  76.   
  77.   [receivedData release];   
  78.    NSLog(@"Connection failed! Error - %@ %@",   
  79.           [error localizedDescription],   
  80.           [[error userInfo] objectForKey:NSErrorFailingURLStringErrorKey]);   
  81. }   
  82.   
  83. 最後,如果連接請求成功的下載,代理會接收connectionDidFinishLoading:消息   
  84. 代理不會收到其他的消息了,在消息的實現中,應該釋放掉連接   
  85.   
  86. 舉例:   
  87. -(oid)connectionDidFinishLoading:(NSURLConnection*)connection   
  88. {   
  89.    //do something with the data   
  90.   NSLog(@“succeeded  %d byte received”,[receivedData length]);   
  91.   
  92. [connection release];   
  93. [receivedData release];   
  94.   
  95. }   
  96.   
  97.   
  98. 好的,初步的流程就是這些   


一些理論知識:

網絡層是iOS開發必須掌握的部分,蘋果已經將網絡請求封裝得非常易用了,看看NSURLRequest和NSURLConnection的文檔,你就知道怎麼用了。本文主要講網絡層的調用邏輯,以及如何優化你的網絡請求,讓請求更有效率。

正常的網絡請求的過程一般經歷四個過程:

1.組裝Request對象,創建Connection對象,當Connection創建完畢後,系統底層會幫你完成3次握手、建立真正的連接等操作

2.收到迴應,會調用ConnectionDelegate的didReceiveResponse方法,這是接收數據的第一步,你需要創建一個data緩衝區

3.然後一點點接收數據,會重複調用didReceiveData,這個方法被調用的次數取決於設備當時的網絡狀況和數據總量,你需要把接收到的數據一點點追加到data緩衝區裏

4.接收完成,會調用connectionDidFinishLoading方法,表明數據全部接收完畢。

 

A:整個過程是異步的,但delegate方法永遠會在主線程執行,蘋果爲保證動畫(如scrollView滑動)的流暢,給了動畫最高的優先級,所以界面動畫會阻塞以上任意一個過程,保證界面不被卡住。於是你應該明白了,儘量不要在做動畫的時候去髮網絡請求,這是徒勞的。

B:當有若干個網絡請求同時發送時,connection對象可以幾乎同時被構建,但系統底層未必會爲所有的連接對象都創建真正的網絡連接,至於底層最多能同時建立多少個真正的網絡連接,我還不清楚。建立了網路連接的請求,哪個先收到Response,就先處理哪個,處理的過程是2-3-4過程依次調用,直到一個請求處理完畢,才接收下一個。於是你應該明白了,要避免同時發送多個請求,尤其是關乎更新界面的請求,一定要單獨發。

C:如果網絡請求進行了一半時退出程序,大家都知道這時候程序會被掛起,那麼網絡連接怎麼辦呢?實際上當程序退出時,系統並不會立即掛起應用進程,而是會延遲大概一秒,如果這樣請求還是沒有完成,系統底層會默默地幫你把數據都接收完,幫你保存請求超時時間那麼久。比如你設置超時時間30s,30s內重新打開應用,數據就立刻全都一次性收到,如果沒打開,不好意思,下次打開程序時,delegate的didFailWithError方法會被調用,通知你請求超時了。


發佈了4 篇原創文章 · 獲贊 8 · 訪問量 21萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章