NSURLConnection和Runloop

- 1.1 涉及知识点

(1)两种为NSURLConnection设置代理方式的区别

    //第一种设置方式:
    //通过该方法设置代理,会自动的发送请求
    // [[NSURLConnection alloc]initWithRequest:request delegate:self];

    //第二种设置方式:
    //设置代理,startImmediately为NO的时候,该方法不会自动发送请求
    NSURLConnection *connect = [[NSURLConnection alloc]initWithRequest:request delegate:self startImmediately:NO];
    //手动通过代码的方式来发送请求
    //注意该方法内部会自动的把connect添加到当前线程的RunLoop中在默认模式下执行
    [connect start];
(2)如何控制代理方法在哪个线程调用

    //说明:默认情况下,代理方法会在主线程中进行调用(为了方便开发者拿到数据后处理一些刷新UI的操作不需要考虑到线程间通信)
    //设置代理方法的执行队列
    [connect setDelegateQueue:[[NSOperationQueue alloc]init]];

(3)开子线程发送网络请求的注意点,适用于自动发送网络请求模式

     //使用GCD开启一个子线程来发送网络请求
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        //使用非自动发送网络请求模式,发送请求OK
        /*
        //创建NSURLConnection对象,设置代理,暂不发送
      NSURLConnection *connect =  [[NSURLConnection alloc]initWithRequest:request delegate:self startImmediately:NO];
        //设置代理方法的执行队列
        [connect setDelegateQueue:[[NSOperationQueue alloc]init]];

        //调用start发送网络请求
        [connect start];
        */

        //使用自动发送网络请求模式,发送请求失败(需要改造代码)
        //WHY?
        /*01 网络请求发送和数据接收是否成功,和一些因素相关,比如客户端的网速、服务器端的查询速度等等。
          02 而在子线程中创建的NSURLConnection对象是一个临时变量,当请求发送完成之后就被释放了,所以这个时候它的代理方法不会调用用。
          03 为什么使用非自动发送网络请求模式是OK的。
            因为在该模式中,调用了start来开始发送网络请求,该方法内部会自动将当前的connect作为一个Source添加到当前线程所在的Runloop中
            如果当前线程是子线程(即当前线程的runloop并未创建),那么该方法内部会默认先创建当前线程的Runloop,设置在runloop的默认模式下运行。
            此时runloop会对这个Connect对象进行强引用,保证了代理方法被调用的前提
         */
        NSURLConnection *connect = [[NSURLConnection alloc]initWithRequest:request delegate:self];
        [connect setDelegateQueue:[[NSOperationQueue alloc]init]];
        //创建当前线程的runloop,并开启runloop
        [[NSRunLoop currentRunLoop] run];
    });
原文地址:https://www.cnblogs.com/HMJ-29/p/4943896.html