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 ...
随机推荐
- "use strict"
"use strict";//严格模式 <!doctype html> <html> <head> <meta charset=" ...
- selenium常见的疑问和问题
.确认(verifation)和断言(assert)有什么区别? 确认:当测试中的一个用例存在错误时,系统将会继续运行这些测试 断言:当测试中的一个用例存在错误时,系统将会退出当前用例 总而言之 ...
- spring获取ApplicationContext对象的方法——ApplicationContextAware
一. 引言 工作之余,在看一下当年学的spring时,感觉我们以前都是通过get~ set~方法去取spring的Ioc取bean,今天就想能不能换种模型呢?因为我们在整合s2sh时,也许有那么一天就 ...
- maven运行javaWeb项目
首先从svn下载下来的maven项目,需要点击项目,然后import--->Existing Maven Projects->全选之后点next就转换成功了,然后 run as--> ...
- HDU #5507 GT and Strings
这是AC自动机系列的第一篇 传送门 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Othe ...
- A.2 Main
程序的执行从类Main的方法main开始.方法main创建了一个词法分析器和一个语法分析器,然后调用语法分析器中的方法program. 1: package main: 2: import java. ...
- visual studio 2012如何彻底删除TFS上的团队项目
http://www.cnblogs.com/zfanlong1314/p/3378441.html 本人的TFS地址:https://zfanlong1314.visualstudio.com/ 最 ...
- EasyUI queryParams属性 在请求远程数据同时给action方法传参
http://www.cnblogs.com/iack/p/3530500.html?utm_source=tuicool EasyUI queryParams属性 在请求远程数据同时给action方 ...
- hdu 2050 折线分割平面
训练递推用题,第一次做这个题,蒙的,而且对了. #include <stdio.h> int main(void) { int c,a; scanf("%d",& ...
- Office Web Apps资源
http://www.cnblogs.com/poissonnotes/p/3277280.html#!comments http://www.cnblogs.com/poissonnotes/p/3 ...