NSURLConnection和NSRunLoop那些说不清的关系

  • 默认情况会将新建NSURLConnection对象添加当前线程的RunLoop中,如果是在子线程中调用NSURLConnection则可能会有问题, 因为子线程默认没有RunLoop
  • 如下是使用NSURLConnection时的几种方式:
    • 1.如果是在主线程中发送请求,因为主线程的RunLoop永远存在,所以NSURLConnection不会被释放,则程序会执行对应的代理方法。如下:
- (void)viewDidLoad{
    [super viewDidLoad];

    NSURL *url = [NSURL URLWithString:@"http://www.baidu.com"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    // alloc/init方法会自动发送请求
    // 发送请求是同步还是异步?  异步
    NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];

    // 设置回调代理方法在子线程中执行
    [conn setDelegateQueue:[[NSOperationQueue alloc] init]];

    /*或
     NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
    // 设置回调代理方法在子线程中执行
    [conn setDelegateQueue:[[NSOperationQueue alloc] init]];
    [conn start];
    */
}
  • 代理方法
#pragma mark  - NSURLConnectionDataDelegate
// 监听NSURLConnection的回调代理方法是在主线程中执行还是在子线程中执行
// 默认情况下是在主线程中执行的
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    NSLog(@"didReceiveResponse = %@", [NSThread currentThread]);
}
......
  • 2.如果是在子线程中发送请求, 因为子线程默认情况下是没有RunLoop的, 所以NSURLConnection将有可能会被释放:
    • 情况一:如果用initWithRequest:delegate:或调用initWithRequest:delegate: startImmediately:(startImmediately为YES时)方法创建NSURLConnection对象,那么NSURLConnection对象会被释放,则不能再去调用代理方法
    • 情况二:如果是用initWithRequest:delegate: startImmediately:startImmediately为NO时方法时,会调用到NSURLConnection的start方法,那么系统会将NSURLConnection对象添加到当前线程runloop的默认模式下,如果当前线程的runloop不存在,那么系统内部会自动创建一个。
// 情况一:
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"dispatch_async = %@", [NSThread currentThread]);
        NSURL *url = [NSURL URLWithString:@"http://baidu.com"];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
        // 设置回调代理方法在子线程中执行
        [conn setDelegateQueue:[[NSOperationQueue alloc] init]];
    });
  • 解决情况一方法,给子线程创建一个runloop
      dispatch_async(dispatch_get_global_queue(0, 0), ^{
          NSLog(@"dispatch_async = %@", [NSThread currentThread]);
          NSURL *url = [NSURL URLWithString:@"http://baidu.com"];
          // 给子线程创建一个runloop
          NSRunLoop *runloop = [NSRunLoop currentRunLoop];
          NSURLRequest *request = [NSURLRequest requestWithURL:url];
          NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
          // 设置回调代理方法在子线程中执行
          [conn setDelegateQueue:[[NSOperationQueue alloc] init]];
          [runloop run];
      });
    
// 情况二:
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"dispatch_async = %@", [NSThread currentThread]);
        NSURL *url = [NSURL URLWithString:@"http://baidu.com"];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
        // 设置回调代理方法在子线程中执行
        [conn setDelegateQueue:[[NSOperationQueue alloc] init]];
        //  如果调用NSURLConnection的start方法, 那么系统会将NSURLConnection添加到当前线程runloop的默认模式下, 如果当前线程的runloop不存在, 那么系统内部会自动创建一个
        [conn start];
    });
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值