一 RunLoop知识点补充
1 在模拟器中拖拽UITextView的时候对RunLoop模式的影响
—-对该方法的解释: 该方法运行的时候回受到runloop运行模式的影响,默认设置为defaulmode,当拖拽的时候,runloop切换模式,所以不执行
代码块和解释一:
[self.imageView1 performSelector:@selector(setImage:) withObject:[UIImage imageNamed:@"/Users/xiaofeng/Desktop/Snip20160319_18.png"] afterDelay:5.0 inModes:@[UITrackingRunLoopMode,NSDefaultRunLoopMode]];
代码块和解释二:
[self.imageView1 performSelector:@selector(setImage:) withObject:[UIImage imageNamed:@"/Users/xiaofeng/Desktop/Snip20160319_15.png"] afterDelay:2.0];
2 问题:怎么能让一个线程一直活着,然后在特定的情况下,让线程跳转任务
二 常驻线程
3 保证线程不死的方法:创建一个RunLoop循环;然后设置数据源或者定时器
—3.1 第一种方法:开启一个死循环—>比如while死循环,保持线程不死亡,这样虽然能保证线程不死,但是不能保证线程去执行其它的任务(不可取)
—3.2 第二种方法:开启一个RunLoop循环,也可以保证让线程不死,但是开启了需要手动执行,并且需要设置运行模式,否则单单只是开启了RunLoop循环,并没有设置模式的话,RunLoop开启了就直接退出,并不会一直往下执行(开启RunLoop需要完成指定的三个步骤)
4 需求:当点击创建线程的按钮的时候,开始创建一条线程,然后点击让子线程开始干其他的工作的时候,子线程开始执行其他工作
4.1 创建子线程按钮:
#pragma mark - 创建子线程按钮
- (IBAction)creatBtnClick:(id)sender
{
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(task) object:nil];
[thread start];
self.thread = thread;
}
创建子线程按钮中的方法实现: 在task方法中我们只要求打印当前线程就行.
4.2 让子线程开始继续工作:
#pragma mark - 让线程继续工作
- (IBAction)goOnBtnClick:(id)sender
{
[self performSelector:@selector(task2) onThread:self.thread withObject:nil waitUntilDone:YES];
}
问题:如果就这样运行的话,就会报错.
报错原因:虽然上面在创建子线程中已经写了一句self.thread = thread保证子线程不会被释放,但是由于没有开启runloop循环,那么子线程其实是处于死亡状态,所以当在点击让子线程继续工作的话就会报错.
4.3 解决办法:创建子线程的RunLoop,让子线程一直在运行,然后通过设置在方法里面的调用其它的需要子线程工作的方法,让子线程去工作
#pragma mark - 工作在线程中的任务
- (void)task
{
NSLog(@"1------%@",[NSThread currentThread]);
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(timeRun) userInfo:nil repeats:YES];
[runLoop addTimer:timer forMode:NSDefaultRunLoopMode];
[runLoop run];
NSLog(@"%s-------2-----%@",__func__,[NSThread currentThread]);
}
注意:上面创建时钟的代码和添加时钟到runloop中的代码可以写成下面一句,同样也能保证线程不处于死亡状态
[runLoop addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
5 RunLoop的自动释放池
5.1 第一次创建 RunLoop启动的时候
5.2 最后一次 RunLoop退出的时候
5.3 其它时间的创建和销毁:当RunLoop即将休眠的时候会把之前的自动释放池销毁,重新创建一个新的
6 RunLoop在网络中的应用(直接看代码就可以)
- (void)delegate1
{
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it&type=JSON"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
NSURLConnection *connention = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
[connention setDelegateQueue:[[NSOperationQueue alloc] init]];
[connention start];
三 网络
1 GET和POST对比:
1.1 GET请求参数直接跟在URL后面(?)
1.2 POST请求参数是在请求体里面
2 HTTP基本通信过程:客户端—>请求—->服务器;服务器—>响应—->客户端
具体的操作步骤:
2.1 确定请求路径
2.2 获取主机名
2.3 DNS域名解析
2.4 获得端口号
2.5 链接到120.25.226.186的端口80
2.6 发送一个HTTP GET请求
2.7 接收服务器的响应
2.8 关闭链接
3 请求和响应
请求:
请求头:包含了客户端的环境描述,客户端请求信息等
请求体:客户端发给服务器的具体数据,比如文件数据(POST请求才会有)
响应:
响应头:包含了对服务器的描述,对返回数据的描述
响应体:服务器返回给客户端的具体数据,比如文件数据
如图:
4 HTTP请求
4.1 HTTP请求的第三方框架:ASIHttpRequest(已经弃用);AFNetworking(主用);MKNetworking
苹果自带的:
1> NSURLConnection:用法简单,最古老最经典最直接的一种方案
2> NSURLSession:功能比NSURLConnection更强大,苹果目前比较推荐的使用技术(重要)
3> CFNetwork:NSURL*的底层,纯C语言
第三方框架:(企业开发基本使用的是第三方框架)
1>ASIHttpRequest:外号”HTTP终结者”,功能极其强大,可惜已经停止更新了
2> AFNetworking:简单易用,提供了基本够用的常用功能,维护和使用者多(重要)
3> MKNsetworking:简单易用,产生三哥的故乡印度,维护和使用者少
四 GET方式
1 概念:发送网络请求的两种方式,主要区别上面已经有写
2 发送同步请求
具体步骤:
1> 确定请求路径
2> 创建请求对象
3> 发送请求
4 > 解析接收数据
#pragma mark - 发送同步请求
- (void)sendSync
{
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it&type=JSON"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSHTTPURLResponse *response = nil;
NSError *error = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}
3 发送异步请求
注意:同步请求和异步请求的主要区别就是发送请求中的方法不同.
#pragma mark - 发送异步请求
- (void)sendAsync
{
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it&type=JSON"];
NSURLRequest *resquest = [NSURLRequest requestWithURL:url];
/** * 参数一:请求对象 * * 参数二:队列(作用在completionHandler上面) * * 参数三:响应的信息(响应头;响应的数据) response 响应头信息 data 响应体信息 connectionError 错误信息 */
[NSURLConnection sendAsynchronousRequest:resquest queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}];
}
4 用代理的方法发送网络请求
注意:需要遵守协议:
<NSURLConnectionDataDelegate>
4.1 代理方法发送,里面包括了设置代理的三种方式
#pragma mark - 代理方法发送请求
- (void)sendAsyncDelegate
{
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it&type=JSON"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection connectionWithRequest:request delegate:self];
NSURLConnection *connecttion1 = [[NSURLConnection alloc] initWithRequest:request delegate:self];
NSURLConnection *connecttion2 = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
[connecttion2 start];
}
4.2 实现代理中的方法
#pragma mark - 代理方法
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(@"%s------%@",__func__,[NSThread currentThread]);
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSLog(@"%s------%@",__func__,[NSThread currentThread]);
self.responseData = [NSMutableData data];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSLog(@"%s------%@",__func__,[NSThread currentThread]);
[self.responseData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(@"%s------%@",__func__,[NSThread currentThread]);
NSLog(@"%@",[[NSString alloc] initWithData:self.responseData encoding:NSUTF8StringEncoding]);
}
五 POST方式
1 直接看代码,上面都标明了
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
request.timeoutInterval = 10;
NSURLResponse *response = nil;
NSError *error = nil;
[request setValue:@"jjjj" forHTTPHeaderField:@"uuuuu"];
request.HTTPBody = [@"username=520it&pwd=520it&type=JSON" dataUsingEncoding:NSUTF8StringEncoding];
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
if (connectionError == nil) {
NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}else{
NSLog(@"%@",connectionError);
}
}];
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}
六 中文转码
1 判断需不需要转码操作:看请求路径是否含有中文,含有的话,就需要转码
2 设置代理的多一个参数的方法中:如果设置的为NO,那么手动开启的时候,底层start会把线程加入到runloop中,但是如果设置的为yes,那么和没有参数的时候一样,需要手动创建runloop.
GET转码:
#pragma mark - GET转码
- (void)get
{
NSString *strurl = @"http://120.25.226.186:32812/login2?username=(需要转的汉字)&pwd=520it&type=JSON";
strurl = [strurl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:strurl];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
if (connectionError == nil) {
NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}else{
NSLog(@"%@",connectionError);
}
}];
}
POST转码:
#pragma mark - POST转码
- (void)post
{
NSString *urlstr = @"http://120.25.226.186:32812/login2";
NSURL *url = [NSURL URLWithString:urlstr];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
request.HTTPBody = [@"username=(需要转的汉字)&pwd=520it&type=JSON" dataUsingEncoding:NSUTF8StringEncoding ];
NSURLResponse *response = nil;
NSError *error = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
if (connectionError == nil) {
NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}else{
NSLog(@"%@",connectionError);
}
}];
}
七 NSURLSession简单使用
1 NSURLSession —->GET用法:一
- (void)get
{
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it&type=JSON"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url ];
NSURLSession *session = [NSURLSession sharedSession];
/** * 参数一:请求对象 * * 参数二:响应头response信息;响应体data信息;error错误信息 * * */
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
NSLog(@"%@",[NSThread currentThread]);
} ];
[dataTask resume];
}
2 GET用法二:
- (void)get1
{
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it&type=JSON"];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
NSLog(@"%@",[NSThread currentThread]);
}];
[dataTask resume];
}
3 GET1和GET2的区别是根据会话对象创建task不同,其实用法还是一样的.
4 POST用法:
- (void)post
{
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login"];
NSMutableURLRequest *resquest = [NSMutableURLRequest requestWithURL:url];
resquest.HTTPMethod = @"POST";
resquest.HTTPBody = [@"username=520it&pwd=520it&type=JSON" dataUsingEncoding:NSUTF8StringEncoding];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:resquest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error == nil) {
NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}else{
NSLog(@"%@",error);
}
NSLog(@"%@",[NSThread currentThread]);
}];
[dataTask resume];
}
八 NSURLSession的代理方法
1 主方法(在里面设置代理)
- (void)sessionGet
{
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it&type=JSON"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request];
[dataTask resume];
}
2 代理方法
2.1 注意: 此代理方法要特别的注意第一个代理方法,因为需要回调告诉系统怎么样处理服务器返回的数据,如果没有写的话,后面两个代理方法是不会调用的,因为completionHandler并没有告诉系统,服务器的数据怎么处理.
#pragma mark - 代理方法
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
{
NSLog(@"%s-------%@",__func__,[NSThread currentThread]);
self.data = [NSMutableData data];
completionHandler(NSURLSessionResponseAllow);
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
NSLog(@"%s-----%@",__func__,[NSThread currentThread]);
[self.data appendData:data];
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
NSLog(@"%s------%@",__func__,[[NSString alloc] initWithData:self.data encoding:NSUTF8StringEncoding]);
NSLog(@"%@",[NSThread currentThread]);
}
九 总结
重复的代码比较多,网络这一块其实比多线程要简单点,只不过需要记忆的东西太多,但是也没关系,多敲就好.里面还有很多不完善的地方,希望大家给予意见,谢谢!!!!