IOS学习——GCD和后台处理

来源:互联网 发布:mac ps2017中文破解版 编辑:程序博客网 时间:2024/05/22 09:38

突然接触了IOS,来到了一个瑰丽的世界,没想到刚开始工作用到的就是大学唯一一丁点都没有接触的东西,sad!

抒情打住……

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()  
这个函数配合分配组队列使用,指定一个额外的代码块,让这部分代码块在所有组的任务全部执行完毕后再执行

用法:
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]);            });            }    });}


写不下去了,明天再补吧,回家睡觉




0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 打架斗殴被关在看守所了怎么办 在看守所羁押期间患癌症怎么办 无法偿还借款拘留15天后怎么办 离婚起诉被告人被羁押怎么办 事实不清的案件怎么办 交通事故没时间去做笔录怎么办 偷东西被拘留家长该怎么办 在香港被拘留了怎么办 发票认证机卡了怎么办 交罚款的单子丢了怎么办 父亲行政拘留考警察政审不过怎么办 非法经营罪立案后不批刑拘怎么办 12分扣完了怎么办2018 驾驶证c1扣14分怎么办 车辆被扣12分怎么办 两个违章扣12分怎么办 车辆违章扣12分怎么办 一下扣了20分怎么办 违章扣了100多分怎么办 车子累计扣12分怎么办 起诉了对方不来怎么办 在监狱里被打伤了怎么办 初三要体检没去怎么办 羁押人在看守所没判刑怎么办? 在看守所关两年了还没有判刑怎么办 开麻将馆被拘留怎么办 拘留31天了我该怎么办 收到一封拘留信怎么办 存钱的收据掉了怎么办 行政拘留法制没有批的怎么办 别人起诉我我该怎么办 去钟落潭看守所送衣服要怎么办 长城宽带账号密码忘了怎么办 预约考试密码忘了怎么办 健康证预约号忘记怎么办啊 人在看守所七个月还没结果怎么办 起诉书和判决书丢了怎么办 进了看守所信用卡逾期怎么办 公安局审讯室监控影相被删除怎么办 关进看守所以前的工作怎么办 上海初中借读生学籍怎么办