NSURLConnection和NSRunLoop那些说不清的关系

来源:互联网 发布:tr罗马布特黑淘宝 编辑:程序博客网 时间:2024/06/06 19:46
  • 默认情况会将新建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