iOS-Network学习笔记(二)——NSURLConnection

原创 2016年06月01日 21:43:08
1. NSURLConnection简介

(1)构造函数和调度函数

- (nullable instancetype)initWithRequest:(NSURLRequest *)request delegate:(nullable id)delegate startImmediately:(BOOL)startImmediately
该方法是NSURLConnection的默认构造函数,startImmediately参数,如果为YES,代表会将当前的connection实例加入到当前的runloop中,该connection的delegate的回调方法都会在当前线程执行,自动实现调度,所以这种情况下甚至是不需要调用 -start方法来开始请求;如果为NO,则需要手动调度,将当前的connection加入到一个线程的runloop中(如果不添加,默认会添加到当前线程的runloop中)。

- (nullable instancetype)initWithRequest:(NSURLRequest *)request delegate:(nullable id)delegate
+ (nullable NSURLConnection*)connectionWithRequest:(NSURLRequest *)request delegate:(nullable id)delegate
上述的实例构造函数和类构造的本质是一样的,最终会调用到默认构造函数,startImmediately参数为YES。

NSURLConnection的执行必须是在一个开启runloop的线程中的,如果执行线程没有开启runloop,connection在start之后,可能会收不到回调方法。PS:主线程的runloop默认是开启的。
在某些开源的网络框架中,开始一个connection的时候,都会开启当前线程的runloop,比如AFNetworking中,所有的网络请求都是在一个特定的线程中执行,这个线程在初始化的时候就开启一个runloop。
+ (void)networkRequestThreadEntryPoint:(id)__unused object {
   
@autoreleasepool {
        [[
NSThread currentThread] setName:@"AFNetworking"];

       
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
        [runLoop
addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
        [runLoop
run];
    }
}

+ (
NSThread *)networkRequestThread {
   
static NSThread *_networkRequestThread = nil;
   
static dispatch_once_t oncePredicate;
   
dispatch_once(&oncePredicate, ^{
        _networkRequestThread = [[
NSThread alloc] initWithTarget:self selector:@selector(networkRequestThreadEntryPoint:) object:nil];
        [_networkRequestThread
start];
    });

   
return _networkRequestThread;
}


SDWebImage框架中,没有特定某个线程来执行connection,而是让operationqueue来分配线程执行,所以在connection start的时候,会开启当前线程的runloop
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_5_1) {
           
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10, false);
        }
       
else {
           
CFRunLoopRun();
        }

手动调度函数有下面三个,前两个是设置/取消connection 回调方法所在的runloop中,第三个直接设置一个operationQueue,将connection的delegate的回调方法交给 queue来调度
- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSRunLoopMode)mode NS_AVAILABLE(10_5, 2_0);
- (
void)unscheduleFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSRunLoopMode)mode NS_AVAILABLE(10_5, 2_0);
- (
void)setDelegateQueue:(nullable NSOperationQueue*) queue NS_AVAILABLE(10_7, 5_0);

(2)start和cancel

        start的方法调用时机,是NSURLConnection创建时startImmediately为NO的时候,要手动调用;cancel方法,提供给我们一个手动结束这个网络连接。-cancel方法,是理论上终止这个网络连接,但是也有可能不起任何作用,deleagte回调方法还会继续;但是如果确定被cancel,delegate就会被释放。

(3)canHandleRequest方法
     
         这个方法,是判断能否通过一个request实例化一个connection。处理方式,是判断这个request能否被请求,正式发送之前的例行检查。

(4)两个category
 
        两个category提供了两个类方法,同步加载以及异步加载,简单处理结果(block回调的形式)。代码如下,第一个是同步加载,会阻塞当前线程;第二个是异步加载,同时会有一个回调block,处理成功的data或者是失败的error
+ (nullable NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse * __nullable * __nullable)response error:(NSError **)error
+ (void)sendAsynchronousRequest:(NSURLRequest*) request
                          queue:(NSOperationQueue*) queue
              completionHandler:(void (^)(NSURLResponse* __nullable response, NSData* __nullable data, NSError* __nullable connectionError)) handler

2.  NSURLConnection Delegate

(1)NSURLConnectionDelegate
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
- (
BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection;
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
如上代码:第一个方法是在connection发生error后进行的回调,(最多回调一次),只要进行回调之后,delegate之后就不会再有回调的方法;第二个是询问connection实例要不要CredentialStorage,不管返回是Y/N,都三个回调都会进行调用的;都三个是connection连接需要进行认证相关的操作回调

(2)NSURLConnectionDataDelegate
- (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;
如上代码:该delegate是将网络数据存储在内存中的回调。第一个方法,是在需要改变request(重定向)的时候,返回一个request来进行继续加载,当然也可以返回nil(connection就会被终止,delegate回调会继续直到finish/error,一般情况下是error);第二个方法,是在收到服务器的响应时进行调用的;第三个方法,是获得网络数据的回调(可能多次调用);第四个方法,是在需要给request增加一些请求body的情况下进行调用的(连接错误或者认证错误),返回nil将会cancel这个connection;第五个方法,是在上传过程中,提供的process回调,(可以计算百分比);第六个方法,是要不要将这个connection的response缓存起来,下次调用可以直接从缓存拿(返回nil,就不能拿;如果进行缓存了,request的参数设置成可以从缓存拿,才会拿着个缓存);最后一个方法,是connection完成的回调。

(3)NSURLConnectionDownloadDelegate
- (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;
- (void)connectionDidFinishDownloading:(NSURLConnection *)connection destinationURL:(NSURL *) destinationURL;
如上代码:该delegate是将网络数据存储在文件中的回调。第一个方法,是获取当前写到文件中的进度;第二个方法是获取断点续传的进度;最后一个方法是必须要实现的,连接结束,提供了暂时存储文件的临时URL,我们需要的是将这个文件的数据转移(如果需要),之后这个临时文件就会被释放。

  

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

iOS-RAC学习笔记(一)——RACStream

RACStream是RACSignal和RACSequence的父类,定义了一些流的操作方法。从名字上可以看出来,这个对象就像流一样可以往任何一个出口流,同时也可以给这个流设计一道道关卡,改变流(这里...

iOS-RAC学习笔记(三)——RACSignal信号流改头换面的祖师Bind

在前面提到了RAC的订阅原理,虽然中间忽略了一些其它东西(比如说RACSchedule,RACDisposable),但任何一个RACSignal的订阅事件的value的流向都是如此。既然是一步步的流...

POST和GET、NSMutableURLRequest和NSURLRequest两组分别的区别

POST和GET: 相同点:都能给服务器传送数据 不同点: 1.给服务器的传输数据的方式 GET:通过网址字符串 POST:通过data 2.传输的数据大小: GET:网址字符串最多25...

ios NSURLRequest NSMutableURLRequest 数据请求

get 请求 #pragma mark - GET登录 - (void)getLogon { // 1. URL NSString *urlStr = [NSString strin...

NSURLRequest详解

URLRequest 的一个实例 // Create the request. //所构建的NSURLRequest具有一个依赖于缓存响应的特定策略,cachePolicy取得策略,timeoutI...

SDK无埋点技术在百分点的探索和实践

2016-10-11 唐星 移动开发前线 移动开发前线 移动开发前线 微信号 bornmobile 功能介绍 专注于分享移动开发前沿和一线技术。 本文为『移...

iOS无埋点数据采集

数据采集

iOS-RAC学习笔记(二)——RACSignal订阅

RACSignal可以说是RAC中最重要的类。RACSignal的订阅是使用RAC的核心机制。 1. RACSignal 订阅机制 a)  RACSignal的创建:RACSign...

iOS-Network学习笔记(一)——NSURLRequest/NSURLResponse

NSURLRequest,NSURLResponse 属性,解释

ios 无码统计埋点

ios无码统计埋点总结 一  第一种方式就是业务代码与统计代码相分离,利用runTime的特性,具体操作如下 定义工具类 @interface WHookUtility : NSObject ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)