详细解析几个和网络请求有关的类(三) —— NSURLConnection

版本记录

版本号 时间
V1.0 2018.03.05

前言

我们做APP发起网络请求,一般都是使用框架,这些框架的底层也都是苹果的API,接下来几篇就一起来看一下和网络有关的几个类。感兴趣的可以看上面几篇文章。
1. 详细解析几个和网络请求有关的类 (一) —— NSURLSession
2. 详细解析几个和网络请求有关的类(二) —— NSURLRequest和NSMutableURLRequest

回顾

上一篇主要介绍了NSURLRequestNSMutableURLRequest的本类和分类的接口使用文档。这一篇主要介绍NSURLConnection。这个类虽然被NSURLSession替代,但是还是拿出来说下吧。


NSURLConnection类

应该不再使用NSURLConnection类。 NSURLSessionNSURLConnection的替代。

NSURLConnection对象提供支持来执行URL请求的异步加载,向客户端代理提供数据。

NSURLConnection的接口非常稀疏,只提供控制来启动和取消URL请求的异步加载。

NSURLConnection可用于将资源数据直接加载到内存,在这种情况下应提供NSURLConnectionDataDelegate,或将资源数据直接下载到文件,在这种情况下使用NSURLConnectionDownloadDelegate。 代理由NSURLConnection保留,直到遇到终止条件。 这两个委托在逻辑上是基本协议NSURLConnectionDelegate的子类。

下载器产生的终止条件将导致连接:didFailWithError:出现错误或connectiondidFinishLoading:connectionDidFinishDownloading:代理消息。

- cancel消息提示加载器应该放弃资源加载,但不能保证更多代理消息不会被传递。 如果- cancel确实会导致负载被放弃,那么代理将被释放,而不会有进一步的消息。 一般来说,调用者应该做好准备,使用方法- cancel,防止产生影响,并在内部忽略任何代理回调,直到代理被释放。

NSURLConnection的调度指定了代理回调的上下文,但实际的IO可能发生在单独的线程上,应该被视为实现细节。

创建时,NSURLConnection执行NSURLRequest的深拷贝。 该副本可通过- originalRequest方法获得。 当连接执行加载时,该请求可能会因协议规范化或由于以下重定向而改变。 - currentRequest可以用来检索这个值。

使用+ connectionWithRequest:delegate:-initWithRequest:delegate:方法创建的NSURLConnections会立即安排在当前的runloop上,并且不需要发送- start消息来开始资源加载。

使用-initWithRequest:delegate:startImmediately创建的NSURLConnections不会自动调度。 使用-scheduleWithRunLoop:forMode:-setDelegateQueue:为委托回调指定上下文,并调用- start开始加载。 如果您在- start之前没有明确地安排连接,它将自动安排在当前的runloop和模式中。

NSURLConnectionSynchronousLoading类别添加了+ sendSynchronousRequest:returningResponse:error,它会阻塞当前线程,直到资源数据可用或发生错误。 应该注意的是,在应用程序主运行循环中使用此方法可能会导致用户界面中的延迟时间过长,强烈建议不这么使用。

NSURLConnectionQueuedLoading类实现了+ sendAsynchronousRequest:queue:completionHandler,提供了类似的简单性,但是提供了一种机制,当前的runloop没有被阻塞。

两种即时加载类别都不提供对资源加载的定制,并且不允许调用者响应例如认证挑战。

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;

// 在运行循环上的调度
- (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.
// 执行“预检”操作,执行一些推测检查以查看是否可以初始化连接,
   并且可以开始在初始化程序方法中启动的关联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.
// 只有没有协议被注册或未注册,并且只要请求没有发生变化(如果请求是可变的),
   此方法的结果也是有效的。 因此,即使客户通过调用此方法执行请求预检,
   也应该准备好处理失败。

    @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,如果可能使用给定的请求来初始化连接并且可以启动关联的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类别提供了执行URL请求同步加载的接口。
   执行给定请求的同步加载,并返回给定输出参数中的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.
// 给定请求的同步加载是建立在类提供的异步加载代码之上的。 调用线程在异步加载系统
// 对专门为此加载请求生成的线程执行URL加载时被阻塞。 为了执行同步加载,
// 在调用线程中不需要特殊的线程或运行循环配置。 例如,调用线程不需要运行它的运行循环。

    @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
       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类别提供了一个接口,用于执行URL请求的异步加载,请求的结果通过NSOperationQueue传递给块的。
// 请注意,此方法不能保证加载的顺序。执行给定请求的异步加载。 当请求完成或失败时,
// 块将从指定的NSOperationQueue的上下文中执行。

    @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的资源。 如果资源加载成功,
// 则回调的数据参数将包含资源数据,错误参数将为nil。 如果资源加载失败,
// 则数据参数将为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是父协议,NSURLConnectionDataDelegateNSURLConnectionDownloadDelegate都继承那个父协议。

后记

本篇讲述了NSURLConnection及其相关的几个代理NSURLConnectionDelegateNSURLConnectionDataDelegateNSURLConnectionDownloadDelegate

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容