IOS学习——GCD和后台处理
2015-11-19 21:33
519 查看
突然接触了IOS,来到了一个瑰丽的世界,没想到刚开始工作用到的就是大学唯一一丁点都没有接触的东西,sad!
抒情打住……
OC也是第一次接触,so~~这么一只菜鸟,使用了Apress两本经典作为入门基础:David Mark《精通IOS开发》+Scott Knaster《Objective-C》。这两本书,水果味的,嘿!之前的笔记都记在了“有道”上,记得不详细,所以冒出在博客上写的想法,可能会督促自己认真一些,边学习边记录了。代码的例子用教材中的,然后加上自己的注释和理解。
GCD(grand central dispatch): 底层队列(多线程优化技术)
这项技术到底应该如何理解我还要看更多官方文档才会有自己的理解,这里直接记录学习过程
注意:块内可以访问在块外定义的变量,如b,但是只能是当块被创建时,这些变量被复制(普通类型int float)或者被保存(指向对象的指针)在块中不可以被更改的同名变量中。就是说,代码块中的b是外面的b复制过来的。
如果要想在块中对块外定义的变量进行写操作,如对a重新赋值,则要把变量a定义为__black int类型!!!
而且这个类型在代码块中被使用后不会被复制和保留。
1、将所有代码包装在一个代码块(Swift称为闭包)中;
2、将该代码块传递给GCD函数dispatch_async函数。
dispatch_async ( param1 , param2 )
param1: 一个GCD队列
param2:代码块
用法:
下面是教材中的一个例子,这个程序是在在文本框中输入字符串,按下start button,显示字符串的长度,超简单!只是在计算字符串长度的时候用sleep一会儿,所以只用主线程来做的话,页面会一直处于挂起(向Android卡死一样)状态,实际上系统在等着sleep的时间过了,在实际的应用中,用户就会觉得这程序崩了,点击什么的全都无效了所以就用到了GCD来处理这个问题,使程序可以不卡在这里:
如果没有拉回主线程的操作,由于后台想GUI更新数据是不可能的,所以运行到刷新数据的语句后,程序会crash,下面是通过@try @catch 获得的错误信息,主要是通信错误:
接下来我不得不说,下面这个设计太让人舒服了!!!
上面后台处理的解决方案只是为了让程序不因为sleepForTimeInterval 而处于挂起模式,但是虽然在底层运行,但我们在时间上还没有进行优化,即:用时还是各方法sleep的总时间,
那么最好的解决方法就是将没有数据干扰的部分并行执行,提高代码的执行速度:这就用到了 分派组 (dispatch group) 可以将需要并行的几块代码放在分派组代码块中,这样各个组内的任务就可以并发执行了!!!
然而,组与组之间处理任务的快慢不同,如果最后的数据更新涉及到所有组,如何判断所有组的任务全部完成了呢?接下来就是真正令我激动的地方——dispatch_group_notify()
这个函数配合分配组队列
ada7
使用,指定一个额外的代码块,让这部分代码块在所有组的任务全部执行完毕后再执行
用法:
写不下去了,明天再补吧,回家睡觉
抒情打住……
OC也是第一次接触,so~~这么一只菜鸟,使用了Apress两本经典作为入门基础:David Mark《精通IOS开发》+Scott Knaster《Objective-C》。这两本书,水果味的,嘿!之前的笔记都记在了“有道”上,记得不详细,所以冒出在博客上写的想法,可能会督促自己认真一些,边学习边记录了。代码的例子用教材中的,然后加上自己的注释和理解。
GCD(grand central dispatch): 底层队列(多线程优化技术)
这项技术到底应该如何理解我还要看更多官方文档才会有自己的理解,这里直接记录学习过程
1.代码块
代码块这个概念在Java中只是在静态块static{ }记得有这么个名词,没想到在OC和swift中运用如此频繁!在Swift中,又称为闭包,不夸张地将,闭包是Swift的一等公民,可以将闭包赋值给变量、传递给方法或者作为调用的返回结果。闭包和等价于OC中的代码块,代码块十分有助于GCD的应用。<pre name="code" class="objc">//声明一个返回值为空,参数为空的块变量 void (^loggerBlock)(void) __block int a=0; int b=1; loggerBlock^{ <span style="white-space:pre"> </span>a=9; <span style="white-space:pre"> </span>nslog(@"%d",b); } //执行 loggerBlock();
注意:块内可以访问在块外定义的变量,如b,但是只能是当块被创建时,这些变量被复制(普通类型int float)或者被保存(指向对象的指针)在块中不可以被更改的同名变量中。就是说,代码块中的b是外面的b复制过来的。
如果要想在块中对块外定义的变量进行写操作,如对a重新赋值,则要把变量a定义为__black int类型!!!
而且这个类型在代码块中被使用后不会被复制和保留。
2.GCD处理
*为了让某个方法在后台运行,只需要1、将所有代码包装在一个代码块(Swift称为闭包)中;
2、将该代码块传递给GCD函数dispatch_async函数。
dispatch_async ( param1 , param2 )
param1: 一个GCD队列
param2:代码块
用法:
//1.声明GCD队列 dispatch_queue_t globalQueue = dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT/HIGH/LOW); //2.实现希望后台运行的代码块 dispatch_async ( globalQueue , ^{ //do something in 后台线程 3//得到希望的数据后,回到主线程进行更新 dispatch_async (dispatch_get_main_queue() , ^{ do something in 主线程 }); });
下面是教材中的一个例子,这个程序是在在文本框中输入字符串,按下start button,显示字符串的长度,超简单!只是在计算字符串长度的时候用sleep一会儿,所以只用主线程来做的话,页面会一直处于挂起(向Android卡死一样)状态,实际上系统在等着sleep的时间过了,在实际的应用中,用户就会觉得这程序崩了,点击什么的全都无效了所以就用到了GCD来处理这个问题,使程序可以不卡在这里:
-(void)doWork:(id)sender{ self.resultsTextView.text = @""; NSDate *startTime = [NSDate date]; //后台处理的时候button不可按,并且出现加载动画 self.startButton.enabled = NO; [self.spinner startAnimating]; dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(globalQueue, ^{ @try{ NSString *fetchedData = [self fetchSomethingFromServer]; NSString *processData = [self processData:fetchedData]; NSString *firstData = [self calculateFirstResult:processData]; NSString *secondData = [self calculateSecondResult:processData]; NSString *resultData = [NSString stringWithFormat:@"%@ \n %@",firstData,secondData]; //update in main queue dispatch_async(dispatch_get_main_queue(), ^{ self.resultsTextView.text = resultData; self.startButton.enabled = YES; [self.spinner stopAnimating]; }); NSDate *endTime = [NSDate date]; NSLog(@"Complete in %f time",[endTime timeIntervalSinceDate:startTime]); }@catch (NSException *e){ NSLog(@"%@",e); } }); }
如果没有拉回主线程的操作,由于后台想GUI更新数据是不可能的,所以运行到刷新数据的语句后,程序会crash,下面是通过@try @catch 获得的错误信息,主要是通信错误:
接下来我不得不说,下面这个设计太让人舒服了!!!
上面后台处理的解决方案只是为了让程序不因为sleepForTimeInterval 而处于挂起模式,但是虽然在底层运行,但我们在时间上还没有进行优化,即:用时还是各方法sleep的总时间,
那么最好的解决方法就是将没有数据干扰的部分并行执行,提高代码的执行速度:这就用到了 分派组 (dispatch group) 可以将需要并行的几块代码放在分派组代码块中,这样各个组内的任务就可以并发执行了!!!
然而,组与组之间处理任务的快慢不同,如果最后的数据更新涉及到所有组,如何判断所有组的任务全部完成了呢?接下来就是真正令我激动的地方——dispatch_group_notify()
这个函数配合分配组队列
ada7
使用,指定一个额外的代码块,让这部分代码块在所有组的任务全部执行完毕后再执行
用法:
dispatch_queue_t globalQueue = dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT/HIGH/LOW); dispatch_async ( globalQueue , ^{ dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group , queue,^{ function1(); }); dispatch_group_async(group , queue,^{ function2(); }); dispatch_async_notify(group , queue , ^{ dispatch_async (dispatch_get_main_queue() , ^{ do something in 主线程 }); }); });运用到例子中就是
<pre name="code" class="objc">-(void)doWork2:(id)sender{ self.resultsTextView.text = @""; NSDate *startTime = [NSDate date]; //后台处理的时候button不可按,并且出现加载动画 self.startButton.enabled = NO; self.startButton.alpha = 0.5; [self.spinner startAnimating]; dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(queue, ^{ NSString *fetchedData = [self fetchSomethingFromServer]; NSString *processData = [self processData:fetchedData]; //NSString *firstData = [self calculateFirstResult:processData]; //NSString *secondData = [self calculateSecondResult:processData]; //NSString *resultData = [NSString stringWithFormat:@"%@ \n %@",firstData,secondData]; __block NSString *firstData;//need to be assigned in block __block NSString *secondData; dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, queue, ^{ <span style="white-space:pre"> </span>firstData = [self calculateFirstResult:processData];//firstData需在块内进行赋值,所以要声明成__block变量,两个"_"哦 }); dispatch_group_async(group, queue, ^{ secondData = [self calculateSecondResult:processData]; }); dispatch_group_notify(group, queue, ^{ NSString *resultData = [NSString stringWithFormat:@"%@\n%@",firstData,secondData]; //update in main queue dispatch_async(dispatch_get_main_queue(), ^{ self.resultsTextView.text = resultData; self.startButton.enabled = YES; self.startButton.alpha = 1.0; [self.spinner stopAnimating]; }); NSDate *endTime = [NSDate date]; NSLog(@"Complete in %f time",[endTime timeIntervalSinceDate:startTime]); }); } }); }
写不下去了,明天再补吧,回家睡觉
相关文章推荐
- Servlet3.1应用生命周期事件 (转载)
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 不可修补的 iOS 漏洞可能导致 iPhone 4s 到 iPhone X 永久越狱
- iOS 12.4 系统遭黑客破解,漏洞危及数百万用户
- 每日安全资讯:NSO,一家专业入侵 iPhone 的神秘公司
- [转][源代码]Comex公布JailbreakMe 3.0源代码
- android横竖屏切换时候Activity的生命周期
- android生命周期深入分析(一)
- IIS处理Asp.net请求和Asp.net页面生命周期说明
- ASP.NET Web页生命周期和执行的方法介绍
- 讲解iOS开发中基本的定位功能实现
- js判断客户端是iOS还是Android等移动终端的方法
- IOS开发环境windows化攻略
- 浅析iOS应用开发中线程间的通信与线程安全问题
- 检测iOS设备是否越狱的方法
- Objective-C的内省(Introspection)用法小结
- .net平台推送ios消息的实现方法
- 关于PHP5 Session生命周期介绍