詳細解析幾個和網(wǎng)絡請求有關的類(三) —— NSURLConnection

版本記錄

版本號 時間
V1.0 2018.03.05

前言

我們做APP發(fā)起網(wǎng)絡請求,一般都是使用框架锭弊,這些框架的底層也都是蘋果的API填硕,接下來幾篇就一起來看一下和網(wǎng)絡有關的幾個類。感興趣的可以看上面幾篇文章炼吴。
1. 詳細解析幾個和網(wǎng)絡請求有關的類 (一) —— NSURLSession
2. 詳細解析幾個和網(wǎng)絡請求有關的類(二) —— NSURLRequest和NSMutableURLRequest

回顧

上一篇主要介紹了NSURLRequestNSMutableURLRequest的本類和分類的接口使用文檔本鸣。這一篇主要介紹NSURLConnection。這個類雖然被NSURLSession替代硅蹦,但是還是拿出來說下吧荣德。


NSURLConnection類

應該不再使用NSURLConnection類。 NSURLSessionNSURLConnection的替代童芹。

NSURLConnection對象提供支持來執(zhí)行URL請求的異步加載涮瞻,向客戶端代理提供數(shù)據(jù)。

NSURLConnection的接口非常稀疏假褪,只提供控制來啟動和取消URL請求的異步加載署咽。

NSURLConnection可用于將資源數(shù)據(jù)直接加載到內(nèi)存,在這種情況下應提供NSURLConnectionDataDelegate,或將資源數(shù)據(jù)直接下載到文件宁否,在這種情況下使用NSURLConnectionDownloadDelegate窒升。 代理由NSURLConnection保留,直到遇到終止條件慕匠。 這兩個委托在邏輯上是基本協(xié)議NSURLConnectionDelegate的子類饱须。

下載器產(chǎn)生的終止條件將導致連接:didFailWithError:出現(xiàn)錯誤或connectiondidFinishLoading:connectionDidFinishDownloading:代理消息。

- cancel消息提示加載器應該放棄資源加載台谊,但不能保證更多代理消息不會被傳遞蓉媳。 如果- cancel確實會導致負載被放棄,那么代理將被釋放锅铅,而不會有進一步的消息酪呻。 一般來說,調(diào)用者應該做好準備盐须,使用方法- cancel号杠,防止產(chǎn)生影響,并在內(nèi)部忽略任何代理回調(diào)丰歌,直到代理被釋放姨蟋。

NSURLConnection的調(diào)度指定了代理回調(diào)的上下文,但實際的IO可能發(fā)生在單獨的線程上立帖,應該被視為實現(xiàn)細節(jié)眼溶。

創(chuàng)建時,NSURLConnection執(zhí)行NSURLRequest的深拷貝晓勇。 該副本可通過- originalRequest方法獲得堂飞。 當連接執(zhí)行加載時,該請求可能會因協(xié)議規(guī)范化或由于以下重定向而改變绑咱。 - currentRequest可以用來檢索這個值绰筛。

使用+ connectionWithRequest:delegate:-initWithRequest:delegate:方法創(chuàng)建的NSURLConnections會立即安排在當前的runloop上,并且不需要發(fā)送- start消息來開始資源加載描融。

使用-initWithRequest:delegate:startImmediately創(chuàng)建的NSURLConnections不會自動調(diào)度铝噩。 使用-scheduleWithRunLoop:forMode:-setDelegateQueue:為委托回調(diào)指定上下文,并調(diào)用- start開始加載窿克。 如果您在- start之前沒有明確地安排連接骏庸,它將自動安排在當前的runloop和模式中。

NSURLConnectionSynchronousLoading類別添加了+ sendSynchronousRequest:returningResponse:error年叮,它會阻塞當前線程具被,直到資源數(shù)據(jù)可用或發(fā)生錯誤。 應該注意的是只损,在應用程序主運行循環(huán)中使用此方法可能會導致用戶界面中的延遲時間過長一姿,強烈建議不這么使用。

NSURLConnectionQueuedLoading類實現(xiàn)了+ sendAsynchronousRequest:queue:completionHandler,提供了類似的簡單性叮叹,但是提供了一種機制艾栋,當前的runloop沒有被阻塞。

兩種即時加載類別都不提供對資源加載的定制衬横,并且不允許調(diào)用者響應例如認證挑戰(zhàn)裹粤。

1. NSURLConnection本類

下面我們就看一下NSURLConnection類的API文檔终蒂。

@interface NSURLConnection : NSObject
{
    @private
    NSURLConnectionInternal *_internal;
}

/* Designated initializer */
// 這幾個都是初始化方法
- (nullable instancetype)initWithRequest:(NSURLRequest *)request delegate:(nullable id)delegate startImmediately:(BOOL)startImmediately API_DEPRECATED("Use NSURLSession (see NSURLSession.h)", macos(10.5,10.11), ios(2.0,9.0), tvos(9.0,9.0)) __WATCHOS_PROHIBITED;

- (nullable instancetype)initWithRequest:(NSURLRequest *)request delegate:(nullable id)delegate API_DEPRECATED("Use NSURLSession (see NSURLSession.h)", macos(10.3,10.11), ios(2.0,9.0), tvos(9.0,9.0)) __WATCHOS_PROHIBITED;
+ (nullable NSURLConnection*)connectionWithRequest:(NSURLRequest *)request delegate:(nullable id)delegate API_DEPRECATED("Use NSURLSession (see NSURLSession.h)", macos(10.3,10.11), ios(2.0,9.0), tvos(9.0,9.0)) __WATCHOS_PROHIBITED;

@property (readonly, copy) NSURLRequest *originalRequest API_AVAILABLE(macos(10.8), ios(5.0), watchos(2.0), tvos(9.0));
@property (readonly, copy) NSURLRequest *currentRequest API_AVAILABLE(macos(10.8), ios(5.0), watchos(2.0), tvos(9.0));

// 開始和取消
- (void)start API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
- (void)cancel;

// 在運行循環(huán)上的調(diào)度
- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSRunLoopMode)mode API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
- (void)unscheduleFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSRunLoopMode)mode API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
- (void)setDelegateQueue:(nullable NSOperationQueue*) queue API_AVAILABLE(macos(10.7), ios(5.0), watchos(2.0), tvos(9.0));


/*! 
    @method         canHandleRequest:

    @abstract
                    Performs a "preflight" operation that performs
                    some speculative checks to see if a connection can
                    be initialized, and the associated I/O that is
                    started in the initializer methods can begin.
// 執(zhí)行“預檢”操作蜂林,執(zhí)行一些推測檢查以查看是否可以初始化連接,
   并且可以開始在初始化程序方法中啟動的關聯(lián)I / O拇泣。

    @discussion
                    The result of this method is valid only as long as
                    no protocols are registered or unregistered, and
                    as long as the request is not mutated (if the
                    request is mutable). Hence, clients should be
                    prepared to handle failures even if they have
                    performed request preflighting by calling this
                    method.
// 只有沒有協(xié)議被注冊或未注冊噪叙,并且只要請求沒有發(fā)生變化(如果請求是可變的),
   此方法的結果也是有效的霉翔。 因此睁蕾,即使客戶通過調(diào)用此方法執(zhí)行請求預檢,
   也應該準備好處理失敗债朵。

    @param 
        request     The request to preflight.

    @result         YES if it is likely that the given request can be used to
                    initialize a connection and the associated I/O can be
                    started, NO otherwise.
// YES子眶,如果可能使用給定的請求來初始化連接并且可以啟動關聯(lián)的I / O,否則返回NO序芦。
 
*/
+ (BOOL)canHandleRequest:(NSURLRequest *)request;

@end

2. NSURLConnection分類NSURLConnectionSynchronousLoading

@interface NSURLConnection (NSURLConnectionSynchronousLoading)

/*! 
    @method      sendSynchronousRequest:returningResponse:error:

    @abstract 
                 Performs a synchronous load of the given request,
                 returning an NSURLResponse in the given out
                 parameter.
// NSURLConnection上的NSURLConnectionSynchronousLoading類別提供了執(zhí)行URL請求同步加載的接口臭杰。
   執(zhí)行給定請求的同步加載,并返回給定輸出參數(shù)中的NSURLResponse

    @discussion
                 A synchronous load for the given request is built on
                 top of the asynchronous loading code made available
                 by the class.  The calling thread is blocked while
                 the asynchronous loading system performs the URL load
                 on a thread spawned specifically for this load
                 request. No special threading or run loop
                 configuration is necessary in the calling thread in
                 order to perform a synchronous load. For instance,
                 the calling thread need not be running its run loop.
// 給定請求的同步加載是建立在類提供的異步加載代碼之上的谚中。 調(diào)用線程在異步加載系統(tǒng)
// 對專門為此加載請求生成的線程執(zhí)行URL加載時被阻塞渴杆。 為了執(zhí)行同步加載,
// 在調(diào)用線程中不需要特殊的線程或運行循環(huán)配置宪塔。 例如磁奖,調(diào)用線程不需要運行它的運行循環(huán)。

    @param
       request   The request to load. Note that the request is
                 deep-copied as part of the initialization
                 process. Changes made to the request argument after
                 this method returns do not affect the request that is
                 used for the loading process.
// 加載的請求某筐。 請注意比搭,該請求是作為初始化過程的一部分進行深度復制的。 
// 此方法返回后對請求參數(shù)所做的更改不會影響用于加載過程的請求南誊。

    @param
       response  An out parameter which is filled in with the
                 response generated by performing the load.

    @param
       error     Out parameter (may be NULL) used if an error occurs
                 while processing the request. Will not be modified if the 
                 load succeeds.

    @result      The content of the URL resulting from performing the load,
                 or nil if the load failed.
*/
+ (nullable NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse * _Nullable * _Nullable)response error:(NSError **)error API_DEPRECATED("Use [NSURLSession dataTaskWithRequest:completionHandler:] (see NSURLSession.h", macos(10.3,10.11), ios(2.0,9.0), tvos(9.0,9.0)) __WATCHOS_PROHIBITED;

@end

3. NSURLConnection分類NSURLConnectionQueuedLoading

@interface NSURLConnection (NSURLConnectionQueuedLoading)

/*!
    @method       sendAsynchronousRequest:queue:completionHandler:

    @abstract 
                  Performs an asynchronous load of the given
                  request. When the request has completed or failed,
                  the block will be executed from the context of the
                  specified NSOperationQueue.
// NSURLConnection上的NSURLConnectionQueuedLoading類別提供了一個接口敢辩,用于執(zhí)行URL請求的異步加載,請求的結果通過NSOperationQueue傳遞給塊的弟疆。
// 請注意戚长,此方法不能保證加載的順序。執(zhí)行給定請求的異步加載怠苔。 當請求完成或失敗時同廉,
// 塊將從指定的NSOperationQueue的上下文中執(zhí)行。

    @discussion
                  This is a convenience routine that allows for
                  asynchronous loading of an url based resource.  If
                  the resource load is successful, the data parameter
                  to the callback will contain the resource data and
                  the error parameter will be nil.  If the resource
                  load fails, the data parameter will be nil and the
                  error will contain information about the failure.
// 這是一個便利的例程,它允許異步加載基于url的資源迫肖。 如果資源加載成功锅劝,
// 則回調(diào)的數(shù)據(jù)參數(shù)將包含資源數(shù)據(jù),錯誤參數(shù)將為nil蟆湖。 如果資源加載失敗故爵,
// 則數(shù)據(jù)參數(shù)將為nil,并且錯誤將包含有關失敗的信息隅津。

    @param
         request   The request to load. Note that the request is
                   deep-copied as part of the initialization
                   process. Changes made to the request argument after
                   this method returns do not affect the request that
                   is used for the loading process.

    @param 
         queue     An NSOperationQueue upon which    the handler block will
                   be dispatched.

    @param
         handler   A block which receives the results of the resource load.
 */
+ (void)sendAsynchronousRequest:(NSURLRequest*) request
                          queue:(NSOperationQueue*) queue
              completionHandler:(void (^)(NSURLResponse* _Nullable response, NSData* _Nullable data, NSError* _Nullable connectionError)) handler API_DEPRECATED("Use [NSURLSession dataTaskWithRequest:completionHandler:] (see NSURLSession.h", macos(10.7,10.11), ios(5.0,9.0), tvos(9.0,9.0)) __WATCHOS_PROHIBITED;
           
@end

形形色色的代理

1. NSURLConnectionDelegate

@protocol NSURLConnectionDelegate <NSObject>

@optional
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection;
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace API_DEPRECATED("Use -connection:willSendRequestForAuthenticationChallenge: instead.", macos(10.6,10.10), ios(3.0,8.0), watchos(2.0,2.0), tvos(9.0,9.0));
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge API_DEPRECATED("Use -connection:willSendRequestForAuthenticationChallenge: instead.", macos(10.2,10.10), ios(2.0,8.0), watchos(2.0,2.0), tvos(9.0,9.0));
- (void)connection:(NSURLConnection *)connection didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge API_DEPRECATED("Use -connection:willSendRequestForAuthenticationChallenge: instead.", macos(10.2,10.10), ios(2.0,8.0), watchos(2.0,2.0), tvos(9.0,9.0));

@end

2. NSURLConnectionDataDelegate

@protocol NSURLConnectionDataDelegate <NSURLConnectionDelegate>

@optional
- (nullable NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(nullable NSURLResponse *)response;
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;

- (nullable NSInputStream *)connection:(NSURLConnection *)connection needNewBodyStream:(NSURLRequest *)request;
- (void)connection:(NSURLConnection *)connection   didSendBodyData:(NSInteger)bytesWritten
                                                 totalBytesWritten:(NSInteger)totalBytesWritten
                                         totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite;

- (nullable NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse;

- (void)connectionDidFinishLoading:(NSURLConnection *)connection;

@end

3. NSURLConnectionDownloadDelegate

@protocol NSURLConnectionDownloadDelegate <NSURLConnectionDelegate>

@optional
- (void)connection:(NSURLConnection *)connection didWriteData:(long long)bytesWritten totalBytesWritten:(long long)totalBytesWritten expectedTotalBytes:(long long) expectedTotalBytes;
- (void)connectionDidResumeDownloading:(NSURLConnection *)connection totalBytesWritten:(long long)totalBytesWritten expectedTotalBytes:(long long) expectedTotalBytes;

@required
- (void)connectionDidFinishDownloading:(NSURLConnection *)connection destinationURL:(NSURL *) destinationURL;

@end

從這里就可以看出來三個代理方法的關系诬垂,NSURLConnectionDelegate是父協(xié)議,NSURLConnectionDataDelegateNSURLConnectionDownloadDelegate都繼承那個父協(xié)議伦仍。

后記

本篇講述了NSURLConnection及其相關的幾個代理NSURLConnectionDelegate结窘、NSURLConnectionDataDelegateNSURLConnectionDownloadDelegate

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末充蓝,一起剝皮案震驚了整個濱河市隧枫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌谓苟,老刑警劉巖官脓,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異涝焙,居然都是意外死亡卑笨,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門纱皆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來湾趾,“玉大人,你說我怎么就攤上這事派草〔蟛” “怎么了?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵近迁,是天一觀的道長艺普。 經(jīng)常有香客問我,道長鉴竭,這世上最難降的妖魔是什么歧譬? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮搏存,結果婚禮上瑰步,老公的妹妹穿的比我還像新娘。我一直安慰自己璧眠,他們只是感情好缩焦,可當我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布读虏。 她就那樣靜靜地躺著,像睡著了一般袁滥。 火紅的嫁衣襯著肌膚如雪盖桥。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天题翻,我揣著相機與錄音揩徊,去河邊找鬼。 笑死嵌赠,一個胖子當著我的面吹牛塑荒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播猾普,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼袜炕,長吁一口氣:“原來是場噩夢啊……” “哼本谜!你這毒婦竟也來了初家?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤乌助,失蹤者是張志新(化名)和其女友劉穎溜在,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體他托,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡掖肋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了赏参。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片志笼。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖把篓,靈堂內(nèi)的尸體忽然破棺而出纫溃,到底是詐尸還是另有隱情,我是刑警寧澤韧掩,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布紊浩,位于F島的核電站,受9級特大地震影響疗锐,放射性物質(zhì)發(fā)生泄漏坊谁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一滑臊、第九天 我趴在偏房一處隱蔽的房頂上張望口芍。 院中可真熱鬧,春花似錦雇卷、人聲如沸鬓椭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽膘融。三九已至芙粱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間氧映,已是汗流浹背春畔。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留岛都,地道東北人律姨。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像臼疫,于是被迫代替她去往敵國和親择份。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容