版本记录
版本号 | 时间 |
---|---|
V1.0 | 2018.03.05 |
前言
我们做APP发起网络请求,一般都是使用框架,这些框架的底层也都是苹果的API,接下来几篇就一起来看一下和网络有关的几个类。感兴趣的可以看上面几篇文章。
1. 详细解析几个和网络请求有关的类 (一) —— NSURLSession
2. 详细解析几个和网络请求有关的类(二) —— NSURLRequest和NSMutableURLRequest
回顾
上一篇主要介绍了NSURLRequest
和NSMutableURLRequest
的本类和分类的接口使用文档。这一篇主要介绍NSURLConnection
。这个类虽然被NSURLSession替代,但是还是拿出来说下吧。
NSURLConnection类
应该不再使用NSURLConnection
类。 NSURLSession
是NSURLConnection
的替代。
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
是父协议,NSURLConnectionDataDelegate
和NSURLConnectionDownloadDelegate
都继承那个父协议。
后记
本篇讲述了NSURLConnection及其相关的几个代理
NSURLConnectionDelegate
、NSURLConnectionDataDelegate
和NSURLConnectionDownloadDelegate
。