iOS NSURLConnection 和 dispatch_async 错误的使用方法,导致回调方法无法调用
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 错误的使用方法,导致回调方法无法调用的更多相关文章
- iOS开发--UIButton 设置圆角 边框颜色 点击回调方法
UIButton *signBtn = [UIButton buttonWithType:UIButtonTypeCustom]; signBtn.frame = CGRectMake(, , , ) ...
- Java回调方法详解
回调在维基百科中定义为: 在计算机程序设计中,回调函数,是指通过函数参数传递到其他代码的,某一块可执行代码的引用. 其目的是允许底层代码调用在高层定义的子程序. 举个例子可能更明白一些:以Androi ...
- java回调方法、钩子方法以及模板方法模式
在面向对象的语言中,回调则是通过接口或抽象类来实现的,我们把实现这种接口的类称为回调类,回调类的对象称为回调对象,其处理事件的方法叫做回调方法.(摘自百度百科) 那么通过上面那句话将百度百科中的&qu ...
- iOS - NSURLConnection 网络请求
前言 @interface NSURLConnection : NSObject class NSURLConnection : NSObject DEPRECATED: The NSURLConne ...
- iOS 真机测试错误“The application bundle does not contain a valid identifier”
iOS 真机测试错误"The application bundle does not contain a valid identifier" 真机测试的时候报错:"The ...
- iOS开发中常见bug!(内附解答方法)
序言 你是否曾经修复了一个 bug ,随后又发现了一个跟刚修复 bug 有关的 bug ,又或是修复 bug 的方式引起了另一个 bug ? 然而这些问题是绝佳的学习机会.所以我们怎样尽可能多地从修复 ...
- iOS NSURLConnection使用详解
一.整体介绍 NSURLConnection是苹果提供的原生网络访问类,但是苹果很快会将其废弃,且由NSURLSession(iOS7以后)来替代.目前使用最广泛的第三方网络框架AFNetworkin ...
- iOS 真机测试错误“The application could not be verified”
iOS 真机测试错误"The application could not be verified" 真机测试的时候报错:"The application could no ...
- iOS之友盟错误统计解决
http://www.cocoachina.com/ios/20150720/12627.html http://lieyunye.github.io/blog/2013/09/10/how-to-a ...
随机推荐
- BIEE 创建一个简单的分析(2)
步骤: 1.如果BIEE安装在本机,直接登录http://localhost:9704/analytics/ 点击右上方导航菜单中的“新建->分析” 2.选择上节创建的RPD文件中的SCOTT主 ...
- WebLogic10安装图文教程
一 WebLogic安装 1. 打开WebLogic安装程序:oepe11_wls1031.exe(我们选用的是WebLogic 10.3g).如图1-1所示: 2. 进入WebLogic安装的欢迎 ...
- 41.Android之图片放大缩小学习
生活中经常会用到图片放大和缩小,今天简单学习下. 思路:1.添加一个操作图片放大和缩小类; 2. 布局文件中引用这个自定义控件; 3. 主Activity一些修改. 代码如下: 增加图片操作类: ...
- BZOJ-1879 Bill的挑战 状态压缩DP
MD....怎么又是状压....... 1879: [Sdoi2009]Bill的挑战 Time Limit: 4 Sec Memory Limit: 64 MB Submit: 537 Solved ...
- javaScript基础练习题-下拉框制作
1.基础回顾 如何让一个段javascript在文档加载后执行,(因为自己忘了,所以顺便复习一下) window.onload = function(){}; <!DOCTYPE html PU ...
- spring全注解项目
项目结构如下: spring配置 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=&q ...
- Maven学习笔记-02-Maven项目打包配置与测试
一 Maven项目打包配置 1 为整个项目统一指定字符集 <properties> <project.build.sourceEncoding>UTF-</project ...
- Nagios告警和监控主机安装介绍(三)
Nagios邮件告警 配置sendEmail 解压缩tar –zxvf sendEmail-v1.56.tar.gz cd sendEmail-v1.56 将可执行程序复制cp sendEmail / ...
- android button 函数调用栈
Button button=(Button) findViewById(R.id.button);button.setOnClickListener(new Button.OnClickListene ...
- 一分钟认识GitHub
一分钟认识GitHub 机缘巧合之下,我开始使用 GitHub ,但事实上,刚刚入门的我不知道如何才能使 GitHub 发挥他的全部功能.不久之前,我偶然听了李福斯先生对 GitHub 的介绍,受益匪 ...