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

版本記錄

版本號 時間
V1.0 2018.03.05

前言

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

回顧

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


NSURLConnection類

應(yīng)該不再使用NSURLConnection類。 NSURLSessionNSURLConnection的替代。

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

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

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

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

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

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

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

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

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

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

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

兩種即時加載類別都不提供對資源加載的定制,并且不允許調(diào)用者響應(yīng)例如認證挑戰(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í)行“預(yù)檢”操作,執(zhí)行一些推測檢查以查看是否可以初始化連接,
   并且可以開始在初始化程序方法中啟動的關(guān)聯(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ā)生變化(如果請求是可變的),
   此方法的結(jié)果也是有效的。 因此,即使客戶通過調(diào)用此方法執(zhí)行請求預(yù)檢,
   也應(yīng)該準備好處理失敗。

    @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,如果可能使用給定的請求來初始化連接并且可以啟動關(guān)聯(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.
// 加載的請求。 請注意,該請求是作為初始化過程的一部分進行深度復(fù)制的。 
// 此方法返回后對請求參數(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請求的異步加載,請求的結(jié)果通過NSOperationQueue傳遞給塊的。
// 請注意,此方法不能保證加載的順序。執(zhí)行給定請求的異步加載。 當(dāng)請求完成或失敗時,
// 塊將從指定的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,并且錯誤將包含有關(guā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.

    @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

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

后記

本篇講述了NSURLConnection及其相關(guān)的幾個代理NSURLConnectionDelegateNSURLConnectionDataDelegateNSURLConnectionDownloadDelegate。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容