好文章收藏夹

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

2018-03-09  本文已影响32人  刀客传奇

版本记录

版本号 时间
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

上一篇下一篇

猜你喜欢

热点阅读