NSURLConnection

本文介绍了iOS中发送HTTP请求的多种方案,包括苹果原生的NSURLConnection、NSURLSession和CFNetwork,以及第三方库如AFNetworking。详细讲解了NSURLConnection的使用步骤,包括GET和POST请求,以及JSON解析方案,推荐使用NSJSONSerialization。还讨论了文件下载和上传,特别是大文件处理,以及断点下载和文件上传的请求体拼接格式。最后提到了多线程下载和文件压缩解压技术。

iOS中发送HTTP请求的方案

1.苹果原生

NSURLConnection:用法简单,最古老最经典的一种方案(坑比较多)

NSURLSession:功能比NSURLConnection更加强大,苹果目前笔记推荐使用的技术(2013年推出)

CFNetwork:纯C语言

2.第三方框架
ASIHttpRequest:早已停止更新
AFNetworking:简单易用,提供了基本够用的常用功能,维护和使用者众多
MKNetworkKit:简单易用,轻量级,维护和使用者少

NSURLConnection的使用

NSURL:请求地址
NSURLRequest:一个NSURLRequest对象就代表一个请求,它包含的信息有:一个NSURL对象,请求方法,请求头,请求体,请求超时…
NSURLConnection:负责发送请求,建立客户端和服务器的连接,发送数据给服务器,并收集来自服务器的响应数据

使用NSURLConnection发送请求的步骤:
1.创建一个NSURL对象,设置请求路径
2.传入NSURL创建一个NSURLRequest对象,设置请求头和请求体
3.使用NSURLConnection发送请求

使用NSURLConnection发送GET请求

同步网络请求:意味着会阻塞当前线程

//1.确定请求路径
NSURL *url = [NSURL URLWithString:@"http://baidu.com/?username=123&password=123"];
//2.创建请求对象
//请求头不需要设置,默认的请求头
NSHTTPURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
//3.发送请求
/*
  第一个参数:请求对象
  第二个参数:响应头信息
  第三个参数:错误信息
*/
NSURLResponse *response = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request  returningResponse:&response error:nil];
//data就是服务器返回给我们的数据
//解析二进制数据
NSLog(@"%@", [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);

异步网络请求:

//1.确定请求路径
NSURL *url = [NSURL URLWithString:@"http://baidu.com/?username=123&password=123"];
//2.创建请求对象
//请求头不需要设置,默认的请求头
NSHTTPURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
//3.发送请求
/*
  第一个参数:请求对象
  第二个参数:队列,也可以在非主线程调用,决定的是block块在哪个线程调用,而不是整个方法
  第三个参数:回调,当请求结束的时候,回调
*/
NSURLResponse *response = nil;
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable  response, NSData * _Nullable data, NSError * _Nullable connectionError){

	//data就是服务器返回给我们的数据
	//解析二进制数据
	NSLog(@"%@", [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
	//类型转换,强制转换
	NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;
	NSLog(@"%zd",res.statusCode);
}];

设置代理发送异步请求

@property(nonatomic,strong) NSMutableData *resultData;

-(NSMutableData *)resultData{
    if(_resultData == nil){
       _resultData = [NSMutableData data];  
    }
    return _resultData;
}

//1.确定请求路径
NSURL *url = [NSURL URLWithString:@"http://baidu.com/?username=123&password=123"];
//2.创建请求对象
//请求头不需要设置,默认的请求头
NSHTTPURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
//3.1设置代理发送请求  方法1
[NSURLConnection connectionWithRequest:request delegate:self];
//3.2设置代理方法2
[[NSURLConnection alloc]initWithRequest:request delegate:self];
//3.3设置代理方法3   设置YES会发送网络请求  设置NO不会发送网络请求
[[NSURLConnection alloc]initWithRequest:request delegate:self startImmediately:YES];

//当接收到server的响应(连通了server)时会调用
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;

//当接收到server的数据时会调用(可能会被调用多次。每次仅仅传递部分数据)
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [self.resultData appendData:data];
  
}

//请求错误(失败)的时候调用(请求超时\断网\没有网\。一般指client错误)
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;

//当server的数据载入完成时就会调用,请求结束时调用
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
   //在这个方法中解析resultData数据
}


NSURLConnection发送POST请求

//1.确定请求路径
NSURL *url = [NSURL URLWithString:@"http://baidu.com/?username=123&password=123"];
//2.创建请求对象
//请求头不需要设置,默认的请求头
NSHTTPURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//3.修改请求方式
request.HTTPMethod = @"POST";
//设置请求头信息
[request setValue:@"ios 10.1" forHTTPHeaderField:@"User-Agent"];
//设置请求超时时间  不管请求有没有成功,超过10秒之后都认为是失败了
request.timeoutInterval = 10;
//4.设置请求体,字符串--->NSData
request.HTTPBody = [@"userName=123&password=123" dataUsingEncoding:NSUTF8StringEncoding];
//5.发送请求

[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable  response, NSData * _Nullable data, NSError * _Nullable connectionError){

	//data就是服务器返回给我们的数据
	//解析二进制数据
	NSLog(@"%@", [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
	//类型转换,强制转换
	NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;
	NSLog(@"%zd",res.statusCode);
}];

URL中文转码

当url中存在中文时,需要对中文进行转码,否则会报错
[url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

多值参数和中文输出

//1.确定请求路径,如果是多个值需要分开传
NSURL *url = [NSURL URLWithString:@"http://baidu.com/?place=BeiJing&place=Guangzhou"];
//2.创建请求对象
//请求头不需要设置,默认的请求头
NSHTTPURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//5.发送请求
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable  response, NSData * _Nullable data, NSError * _Nullable connectionError){

	//data就是服务器返回给我们的数据
	//如果dict中有中文,则不能正常显示,可以创建一个分类
	NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
	NSLog(@"%@",dict);
}];
//重写NSDictionary的descriptionWithLocale方法
-(NSString *)descriptionWithLocale:(id)locale indent:(NSUInteger)level{
    NSMutableString *string = [NSMutableString string];
    [string appendString:@"{"];
    [self enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop){
        [string appendFormat:@"%@", key];
        [string appendFormat:@"%@,", obj];
    }];
    [string appendString:@""];
    return string;
}

JSON解析方案

第三方框架:JSONKit、SBJson、TouchJSON(性能从左到右越差)

苹果原生的:NSJSONSerialization(性能最好)

NSJSONSerialization

//JSON--->OC对象  反序列化
/*
  NSJSONReadingMutableContainers   可变字典和数组
  NSJSONReadingMutableLeaves       内部所有的字符串都是可变的  ios7之后有问题,一般不用
  NSJSONReadAllowFragments    既不是字典也不是数组,则必须使用该枚举值
*/
+(id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error;
//OC对象--->JSON  序列化
+(NSData *)dataWithJSONObject:(id)obj options:(NSJSONWritingOptions)opt error:(NSError **)error;

注意:并不是所有的OC都能转换成JSON,只有最外层是字典或者数组的才能转,
所有的元素必须是NSString,NSNumber, NSArray, NSDictionary, or NSNull
所有的key必须是string类型
NSNumber不能是无穷大

//判断能不能转化成JSON
BOOL isValid = [NSJSONSerialization isValidJSONObject:dictM];

写入.json文件

先将OC对象转换成JSON字符串,然后再将JSON数据写入.json文件中

面向模型开发

JSON转OC对象,OC对象转模型
字典转模型:KVC

模型中有关键字的时候:(id)
模型中有系统的方法名称:(description)
解决方法:框架Mantle,jsonModel,MJExtension (github搜索)

文件下载和上传

-(void)touchesBegan:(NSSet<UITouch *>touches withEvent:(UIEvent *)event)
{

}
//第一种方法
-(void)download
{
   NSURL *url = [NSURL URLWithString:@"http://1233"];
   //下载二进制数据
   NSData *data = [NSData dataWithContentsOfURL:url];
   //转换
   UIImage *image = [UIImage imageWithData:data];
}
//第二种方法
//无法监听进度
//会立刻导致内存飙升
-(void)download2
{
   NSURL *url = [NSURL URLWithString:@"http://1233"];
   //下载二进制数据
   NSURLRequest *request = [NSURLRequest requestWithURL:url];
   [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue]       completionHandler:^(NSURLResponse * _Nullable  response, NSData * _Nullable data, NSError * _Nullable connectionError){
         //转换,将二进制图片转换为UIImage
         UIImage *image = [UIImage imageWithData:data];
         
   }];
  
}
//设置代理
//进度 = 当前已经下载的文件大小/文件总大小
//同样会导致内存飙升
-(void)download3
{
     NSURL *url = [NSURL URLWithString:@"http://1233"];
      
     NSURLRequest *request = [NSURLRequest requestWithURL:url];
     //3.1设置代理发送请求  方法1
     [NSURLConnection connectionWithRequest:request delegate:self];
}
//当接收到server的响应(连通了server)时会调用
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
      //响应头可以获取文件总大小,本次请求的文件数据总大小
      self.totlSize = response.expectedContentLength;
}
//当接收到server的数据时会调用(可能会被调用多次。每次仅仅传递部分数据)
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [self.resultData appendData:data];
    //在这个方法中计算文件下载进度
    NSLog(@"%f",1.0*self.resultData/self.totalSize);
  
}

//请求错误(失败)的时候调用(请求超时\断网\没有网\。一般指client错误)
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    
}

//当server的数据载入完成时就会调用,请求结束时调用
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
   //在这个方法中解析resultData数据
   //将数据保存到沙盒中
}

上述三种方法都会导致内存飙升,因此只适合小文件的下载

大文件下载为了不让内存突增,我们让文件直接下载到沙盒中,需要用到NSFileManager

-(void)download3
{
     NSURL *url = [NSURL URLWithString:@"http://1233"];
      
     NSURLRequest *request = [NSURLRequest requestWithURL:url];
     //3.1设置代理发送请求  方法1
     [NSURLConnection connectionWithRequest:request delegate:self];
}
//当接收到server的响应(连通了server)时会调用
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
      //响应头可以获取文件总大小,本次请求的文件数据总大小
      self.totalSize = response.expectedContentLength;
       //可以直接将数据写入沙盒
       [[NSFileManager defaultManager] createFileAtPath:self.fullpath content:nil attributes:nil];
       //创建文件距离
       self.handler = [NSFileHandle fileHandleForWritingAtPath:self.fullpath];
    //
}
//当接收到server的数据时会调用(可能会被调用多次。每次仅仅传递部分数据)
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [self.handle seekToEndOfFile];
    //写数据
    [self.handle writeData:data];
    //获得进度
     //[self.resultData appendData:data];
    //在这个方法中计算文件下载进度
    self.currentSize = self.currentSize+data.length;
    NSLog(@"%f",1.0*self.currentSize /self.totalSize);
  
}

//请求错误(失败)的时候调用(请求超时\断网\没有网\。一般指client错误)
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    
}

//当server的数据载入完成时就会调用,请求结束时调用
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    //关闭文件句柄
    [self.handle closeFile];
    self.handle = nil;
}

断点下载 (断点下载需要设置请求头)

@property(nonatomic,strong) NSURLConnection *urlconnection;
-(IBAction)startDownload
{
    NSURL *url = [NSURL URLWithString:@"http://1233"];
      
     NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:url];
     //3.1设置代理发送请求  方法1
     NSString *range = [NSString stringWithFormat:@"bytes=%zd-", self.currentSize];
     //设置请求头
     [request setValue:range  forHTTPHeaderField: @"Range"];
     [NSURLConnection connectionWithRequest:request delegate:self]
}

-(IBAction)cancelBtnDownload
{
     [self.urlconnection cancel];
     //取消下载时不可恢复的
}
//当接收到server的响应(连通了server)时会调用
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{      if(self.currentSize > 0) return;
      //响应头可以获取文件总大小,注意是本次请求的文件数据总大小,不是该文件的原本大小
      self.totalSize = response.expectedContentLength;
       //可以直接将数据写入沙盒
      
       [[NSFileManager defaultManager] createFileAtPath:self.fullpath content:nil attributes:nil];
       //创建文件距离
       self.handler = [NSFileHandle fileHandleForWritingAtPath:self.fullpath];
    //
}
//当接收到server的数据时会调用(可能会被调用多次。每次仅仅传递部分数据)
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [self.handle seekToEndOfFile];
    //写数据
    [self.handle writeData:data];
    //获得进度
     //[self.resultData appendData:data];
    //在这个方法中计算文件下载进度
    self.currentSize = self.currentSize+data.length;
    NSLog(@"%f",1.0*self.currentSize /self.totalSize);
  
}

//请求错误(失败)的时候调用(请求超时\断网\没有网\。一般指client错误)
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    
}

//当server的数据载入完成时就会调用,请求结束时调用
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    //关闭文件句柄
    [self.handle closeFile];
    self.handle = nil;
}

使用输出流实现文件下载

//当接收到server的响应(连通了server)时会调用
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
     if(self.currentSize > 0) return;
      //响应头可以获取文件总大小,注意是本次请求的文件数据总大小,不是该文件的原本大小
      self.totalSize = response.expectedContentLength;
       //可以直接将数据写入沙盒
       self.fullpath = [[NSSearchPathForDirectoriesIndomains(NSCachesDirectionary, NSUserDomainMask, YES)lastObject]stringByAppendingPathComponent:@"123.jpg"];
      //创建输出流
      /*
      第一个参数:文件的路径
      第二个参数:YES,追加;
      特点:如果该输出流指向的地址没有文件,那么会创建一个空的文件
      */
      NSOutputStream *stream = [[NSOutputStream alloc] initToFileAtPath:self.fullpath append:YES];
      //打开输出流
      [stream open];
      self.stream = stream;
}
//当接收到server的数据时会调用(可能会被调用多次。每次仅仅传递部分数据)
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [self.stream write:data.bytes maxLength:data.length];
    //在这个方法中计算文件下载进度
    self.currentSize = self.currentSize+data.length;
    NSLog(@"%f",1.0*self.currentSize /self.totalSize);
  
}

//请求错误(失败)的时候调用(请求超时\断网\没有网\。一般指client错误)
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    
}

//当server的数据载入完成时就会调用,请求结束时调用
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    //关闭文件句柄
    [self.stream close];
    self.stream = nil;
}

NSURLConnection实现文件上传
(1)确定请求路径
(2)根据URL创建一个可变的请求对象
(3)设置请求对象,修改请求方式为POST
(4)设置请求头,告诉服务器我们将要上传文件(Content-Type)
(5)设置请求体(在请求体中按照既定的格式拼接要上传的文件参数和非文件参数等数据)
001 拼接文件参数
002 拼接非文件参数
003 添加结尾标记
(6)使用NSURLConnection sendAsync发送异步请求上传文件
(7)解析服务器返回的数据

请求体拼接格式
分隔符:----WebKitFormBoundaryhBDKBUWBHnAgvz9c

01.文件参数拼接格式

–分隔符
Content-Disposition:参数
Content-Type:参数 image/png(MIMEType 大类型/小类型)
空行
文件参数

02.非文件拼接参数
–分隔符
Content-Disposition:参数
空行
非文件的二进制数据

03.结尾标识
–分隔符–

#define Kboundary @"----WebKitFormBoundaryhBDKBUWBHnAgvz9c"
#define KnewLine [@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]
-(void)upload
{
   //1.确定请求路径
    NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/upload"];

    //2.创建一个可变的请求对象
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

    //3.设置请求方式为POST
    request.HTTPMethod = @"POST";

    //4.设置请求头
    NSString *filed = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",Kboundary];
    [request setValue:filed forHTTPHeaderField:@"Content-Type"];

    //5.设置请求体
    NSMutableData *data = [NSMutableData data];
    //5.1 文件参数
    /*
     --分隔符
     Content-Disposition:参数
     Content-Type:参数
     空行
     文件参数
     */
    [data appendData:[[NSString stringWithFormat:@"--%@",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [data appendData:KnewLine];
    [data appendData:[@"Content-Disposition: form-data; name=\"file\"; filename=\"test.png\"" dataUsingEncoding:NSUTF8StringEncoding]];
    [data appendData:KnewLine];
    [data appendData:[@"Content-Type: image/png" dataUsingEncoding:NSUTF8StringEncoding]];
    [data appendData:KnewLine];
    [data appendData:KnewLine];
    [data appendData:KnewLine];

    UIImage *image = [UIImage imageNamed:@"test"];
    NSData *imageData = UIImagePNGRepresentation(image);
    [data appendData:imageData];
    [data appendData:KnewLine];

    //5.2 非文件参数
    /*
     --分隔符
     Content-Disposition:参数
     空行
     非文件参数的二进制数据
     */

    [data appendData:[[NSString stringWithFormat:@"--%@",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [data appendData:KnewLine];
    [data appendData:[@"Content-Disposition: form-data; name=\"username\"" dataUsingEncoding:NSUTF8StringEncoding]];
    [data appendData:KnewLine];
    [data appendData:KnewLine];
    [data appendData:KnewLine];

    NSData *nameData = [@"abc" dataUsingEncoding:NSUTF8StringEncoding];
    [data appendData:nameData];
    [data appendData:KnewLine];

    //5.3 结尾标识
    //--分隔符--
    [data appendData:[[NSString stringWithFormat:@"--%@--",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [data appendData:KnewLine];

    request.HTTPBody = data;

    //6.发送请求
    [NSURLConnection sendAsynchronousRequest:request 
                     queue:[NSOperationQueue mainQueue] 
                     completionHandler:^(NSURLResponse * __nullable response, 
                                         NSData * __nullable data, 
                                         NSError * __nullable connectionError) {

        //7.解析服务器返回的数据
        NSLog(@"%@",[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]);
    }];
   
}

如何获得文件的MIMEType
(1)直接对该对象发送一个异步网络请求,在响应头中通过response.MIMEType拿到文件的MIMEType类型

//如果想要及时拿到该数据,那么可以发送一个同步请求
- (NSString *)getMIMEType
{
    NSString *filePath = @"/Users/abc/Desktop/123.json";

    NSURLResponse *response = nil;
    [NSURLConnection sendSynchronousRequest:[NSURLRequest 
                     requestWithURL:[NSURL fileURLWithPath:filePath]] 
                     returningResponse:&response error:nil];
    return response.MIMEType;
}

//对该文件发送一个异步请求,拿到文件的MIMEType
- (void)MIMEType
{

    //    NSString *file = @"file:///Users/abc/Desktop/test.png";

    [NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:@"/Users/abc/Desktop/test.png"]] 
                     queue:[NSOperationQueue mainQueue] 
                     completionHandler:^(NSURLResponse * __nullable response, 
                                         NSData * __nullable data, 
                                         NSError * __nullable connectionError) {
        //       response.MIMEType
        NSLog(@"%@",response.MIMEType);

    }];
}

(2)通过UTTypeCopyPreferredTagWithClass方法

//注意:需要依赖于框架MobileCoreServices
- (NSString *)mimeTypeForFileAtPath:(NSString *)path
{
    if (![[[NSFileManager alloc] init] fileExistsAtPath:path]) {
        return nil;
    }

    CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, 
                      (__bridge CFStringRef)[path pathExtension], NULL);
    CFStringRef MIMEType = UTTypeCopyPreferredTagWithClass (UTI, kUTTagClassMIMEType);
    CFRelease(UTI);
    if (!MIMEType) {
        return @"application/octet-stream";
    }
    return (__bridge NSString *)(MIMEType);
}

多线程下载文件

开多个线程下载同一个文件,每个线程下载一部分数据,返回的数据需要先判断一下线程,不同的线程,则需要从下载的地方开始写

文件的压缩和解压

使用ZipArchive来压缩和解压缩文件需要添加依赖库(libz),使用需要包含Main文件,如果使用cocoaPoads来安装框架,那么会自动的配置框架的使用环境

//压缩文件的第一种方式
/*
第一个参数:压缩文件要保存的位置
第二个参数:要压缩哪几个文件
*/
[ZipArchive createZipFileAtPath:fullpath withFilesAtPaths:arrayM];

//压缩文件的第二种方式
/*
第一个参数:文件压缩到哪个地方
第二个参数:要压缩文件的全路径
*/
[ZipArchive createZipFileAtPath:fullpath withContentsOfDirectory:zipFile];

//如何对压缩文件进行解压
/*
第一个参数:要解压的文件
第二个参数:要解压到什么地方
*/
[ZipArchive unzipFileAtPath:unZipFile toDestination:fullpath];

NSURLConnection和Runloop

代理方法的执行是异步的
如果想让代理方法在其它线程中调用
NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
[connection setDelegateQueue:[[NSOperation alloc] init]];  //非主队列,就会开子线程,所有的代理方法都会在子线程中执行

方法2:

NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self startImmediate:YES];//设置YES不会有任何区别,设置NO的话还需要调用  [connection start]才会发送请求
//如果connection对象没有添加到runloop中,那么该方法内部会自动的添加到runloop
//注意:如果当前的runloop没有开启,那么该方法内部会自动获得当前对应的runloop对象并且开启
[connection setDelegateQueue:[[NSOperation alloc] init]];  //非主队列,就会开子线程,所有的代理方法都会在子线程中执行

如果设置代理写在子线程中

dispatch_async(dispatch_get_global_queue(0,0), ^{
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://120.it.com"]];
    //该方法内部其实会将我们的connection对象作为一个source添加到runloop中,指定运行模式为默认,当你的所有代理都执行完毕才会被释放。
    NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
    [connection setDelegateQueue:[[NSOperation alloc] init]]; 
    [[NSRunLoop currentRunloop] run];  //在子线程中需要开启runloop
   
})
这样写的话代理方法会不工作
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值