dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ), ^{
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:urlStr] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:CONNECTIONT_TIMEOUT];
NSString *encodedStr = [body stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSData *sendData = [encodedStr dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
NSString *dataLengthStr =[NSString stringWithFormat:@"%lu",(unsigned long)[sendData length]];
[request setValue:dataLengthStr forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:sendData];
self.connection = [NSURLConnection connectionWithRequest:request delegate:self];
});

这是一个在主线程中执行的代码,执行结果有问题,无法执行网络回调函数。

原因如下:对于connectionWithRequest这个函数在官方文档下有以下说明:

Delegate methods are called on the same thread that called this method.

这就是说,delegate的消息会发送到调用connectionWithRequest方法的线程中去。如果线程结束了,比如这里就是这样,那么,系统就不会调用相应方法,即使delegate对象本身是存在的!

改正方法很简单,有2种

1.把网络请求发送代码放到主线程,就是不使用dispatch_async

2.在dispatch_async 块的结尾处调用

 NSRunLoop *loop = [NSRunLoop currentRunLoop];

 [loop run];

当connection完成回调后,会把自己(source)从runloop中移除,这样这个runloop中就没有任何source和timer了,这个runloop会自动停止,相关线程自动结束。

下面是关于run方法的说明,可见,如果没有input source 和timer 加入nsrunloop,这个run方法会立即返回的(这个经过了测试,也十分重要!)。总结下就是,在一个runloop中还有source时,如果调用了run,那么当runloop的source都没了时,这个run方法会自动返回!

If no input sources or timers are attached to the run loop, this method exits immediately; otherwise, it runs the receiver in the NSDefaultRunLoopMode by repeatedly invoking runMode:beforeDate:. In other words, this method effectively begins an infinite loop that processes data from the run loop’s input sources and timers.

再看看runloop的说明

The NSRunLoop class declares the programmatic interface to objects that manage input sources. An NSRunLoop object processes input for sources such as mouse and keyboard events from the window system, NSPort objects, and NSConnection objects. An NSRunLoop object also processes NSTimer events.

这里说明,nsrunloop主要处理2种消息,一种是input source 一种是timer(注意,nsobject中的performSelector的一系列函数就是利用timer放入到runloop中的),而input source分为4种,分别是鼠标消息,键盘消息,port消息(不太明白),nsconnection (不仅仅是网络连接)消息。

另外还需要注意 You should never try to call the methods of an NSRunLoop object running in a different thread, as doing so might cause unexpected results. 也就是说,不要在其他线程中通过调用 runloop对象让runloop停止!必须放到自己的线程中做,这个错误很容易犯。

这个错误提醒我,在使用dispatch_async时,如果没有特殊操作,相关线程会在block结束后立即退出,仅仅靠系统自动加入的input source(比如这里的nsurlconnection),是无法使线程继续存活的,因为加入input source或timer 后还需要我们启动 runloop才行。除了主线程,系统不会为你自动启动runloop的。

iOS NSURLConnection 和 dispatch_async 错误的使用方法,导致回调方法无法调用的更多相关文章

  1. iOS开发--UIButton 设置圆角 边框颜色 点击回调方法

    UIButton *signBtn = [UIButton buttonWithType:UIButtonTypeCustom]; signBtn.frame = CGRectMake(, , , ) ...

  2. Java回调方法详解

    回调在维基百科中定义为: 在计算机程序设计中,回调函数,是指通过函数参数传递到其他代码的,某一块可执行代码的引用. 其目的是允许底层代码调用在高层定义的子程序. 举个例子可能更明白一些:以Androi ...

  3. java回调方法、钩子方法以及模板方法模式

    在面向对象的语言中,回调则是通过接口或抽象类来实现的,我们把实现这种接口的类称为回调类,回调类的对象称为回调对象,其处理事件的方法叫做回调方法.(摘自百度百科) 那么通过上面那句话将百度百科中的&qu ...

  4. iOS - NSURLConnection 网络请求

    前言 @interface NSURLConnection : NSObject class NSURLConnection : NSObject DEPRECATED: The NSURLConne ...

  5. iOS 真机测试错误“The application bundle does not contain a valid identifier”

    iOS 真机测试错误"The application bundle does not contain a valid identifier" 真机测试的时候报错:"The ...

  6. iOS开发中常见bug!(内附解答方法)

    序言 你是否曾经修复了一个 bug ,随后又发现了一个跟刚修复 bug 有关的 bug ,又或是修复 bug 的方式引起了另一个 bug ? 然而这些问题是绝佳的学习机会.所以我们怎样尽可能多地从修复 ...

  7. iOS NSURLConnection使用详解

    一.整体介绍 NSURLConnection是苹果提供的原生网络访问类,但是苹果很快会将其废弃,且由NSURLSession(iOS7以后)来替代.目前使用最广泛的第三方网络框架AFNetworkin ...

  8. iOS 真机测试错误“The application could not be verified”

    iOS 真机测试错误"The application could not be verified" 真机测试的时候报错:"The application could no ...

  9. iOS之友盟错误统计解决

    http://www.cocoachina.com/ios/20150720/12627.html http://lieyunye.github.io/blog/2013/09/10/how-to-a ...

随机推荐

  1. Python装饰器笔记

    DRY(Don't Repeat Yourself)原则: 一般是指在写代码的时候尽量避免重复的实现.违反DRY原则导致的坏处很容易理解,例如维护困难,修改时一旦遗漏就会产生不易察觉的问题. 一.函数 ...

  2. Spring JdbcTemplate 的使用与学习

    JDBCTemplate 是SPRING 框架自带的一种对sql 语句查询的封装 ,封装非常完善,虽然与Hibernate比起来有一点麻烦,但是学号JDBCTemplate可以让我们用Spirngmv ...

  3. groovy-集合

    Lists 你能使用下面的方法创建一个lists,注意[]是一个空list. 1 def list = [5, 6, 7, 8] 2 assert list.get(2) == 7 3 assert  ...

  4. 最小圆覆盖(Smallest Enclosing Discs)

    随机增量算法(a randomized incremental algorithm) #define sqr(x) ((x)*(x)) #define EPS 1e-4 struct P{ doubl ...

  5. windows上使用image库

    首先要安装这个库,可以使用pip安装,那么我们要首先安装pip 去https://bootstrap.pypa.io/get-pip.py下载get-pip.py,然后运行python get-pip ...

  6. linux下IPTABLES配置详解(转)

    如果你的IPTABLES基础知识还不了解,建议先去看看.开始配置我们来配置一个filter表的防火墙.(1)查看本机关于IPTABLES的设置情况[ ~]# iptables -L -nChain I ...

  7. linux磁盘空间清理

    由于当初安装系统设计不合理,有些分区的过小,以及网络通讯故障等造成日志文件速度增长等其他原因都可以表现为磁盘空间满,造成无法读写磁盘,应用程序无法执行等.下面就给你支几招(以/home空间满为例): ...

  8. jquery------导入jquery.2.2.3.min.js

    问题: 导入jquery.2.2.3.min.js后MyEclipse会提示代码有错误 方法: 选中jquery.2.2.3.min.js->右键->选择“MyEclipse”中的“Exc ...

  9. BurpSuite之HTTP brute暴力破解

    常规的对username/passwprd进行payload测试,我想大家应该没有什么问题,但对于Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=这样的问题, ...

  10. FCK编辑器漏洞总结

    1.查看编辑器版本FCKeditor/_whatsnew.html————————————————————————————————————————————————————————————— 2. Ve ...