【读书笔记】关于GCD

例如下载网页功能。

如果不用GCD,多线程下载,我们要把下载过程放到后台,以免阻塞UI。需要以下三部:

1.someClick:单击按钮后,我们用NSInvocationOperarion建立一个后台线程,并且把这个线程放到NSOperartionQueue中。后台执行download方法。


2 download方法处理下载网页的逻辑。下载完了之后用performSelectorOnMainThread(回到主线程)执行download_completed方法.


3.download_completed 进行clear up工作,把下载的内容显示到文本控件中.(这里我理解的是刷新UI的操作).

static NSOperationQueue *queue;

- (IBAction)someClick:(id)sender {


//    self.indicator.hidden = NO;  //关于下载过程中圈圈的处理

//    [self.indicator startAnimating];

    queue = [[NSOperationQueue alloc]init];  //创建操作队列

    NSInvocationOperation * op = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download) object:nil];  //创建调用操作

    [queue addOperation:op];       //加入队列

    

}


-(void)download {


    NSURL *url = [NSURL URLWithString:@"http://www.baidu.com"];

    NSError *error;

    NSString * data = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];

    if (data != nil) {

        [self performSelectorOnMainThread:@selector(download_completed:) withObject:data waitUntilDone:NO];  //回到主线程 执行下载完成操作

    }else {

    

        NSLog(@"error when download:%@",error);

    }

}

- (void)download_completed:(NSString *)data {   //根据下载完传回的data 做UI刷新显示.


    NSLog(@"call back");

    [self.indicator stopAnimating];

    self.indicator.hidden = YES;

    self.content.text = data;

}


当不用GCD的时候,下载被分成了三个步骤: 开始下载->下载中->下载完成.这三个方法还要互相传递参数,而当传递的参数过于复杂的时候,

就要用到model类,把下载放到model类中做,而界面控制放到viewcontroller层来做,这使得代码变得更加零散.


使用GCD

//代码块一

    self.indicator.hidden = NO//关于下载过程中圈圈的处理

    [self.indicator startAnimating];

    

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        //代码块二

        NSURL *url = [NSURL URLWithString:@"http://baidu.com"];

        

        NSError *error;

        NSString * data = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];

        if (data != nil) {

            

            dispatch_async(dispatch_get_main_queue(), ^{

                //代码块三

                [self.indicator stopAnimating];

                self.indicator.hidden = YES;

                self.content.text = data;

            });

            

        }else {

            

            NSLog(@"error when download:%@",error);

        }

    });


block定义

//声明变量

-(void)(^loggerBlock)(void);


//定义

loggerBlock = ^{


    NSLog(@"hello");

};


//调用

loggerBlock();


内联定义block

即将他的程序块写在调用的函数里面

dispatch_async(dispatch_get_global_queue(0, 0), ^{

        //something

    });


block特点

1.程序块可以在代码中医内联的方式定义

2.程序块可以访问在创建它的范围内的可用变量.



GCD中用了dispatch方法

这事为了方便我们使用GCD,苹果提供了一些方法方便我们将block放在主线程或后台线程执行,或者延后执行.


//后台执行

dispatch_async(dispatch_get_global_queue(00), ^{

        //something

    });


//主线程执行

    dispatch_async(dispatch_get_main_queue(), ^{

        //something

    })

//一次性执行

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        //code to be executed once

    });

//延迟两秒执行

    double delayInSeconds = 2.0;

    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds*NSEC_PER_SEC);

    dispatch_after(popTime, dispatch_get_main_queue(), ^{

        //code to be executed on the main queue after delay

    });


GCD高级用法  

让后台两个线程并行执行,然后等两个线程都结束后,在汇总执行结果.

这个可以用 dispatch_group, dispatch_group_async,dispatch_group_notify来实现


修改block之外的变量

默认情况下,block程序块中的外部变量是复制过去的,即 写操作不对原变量生效,但是外部变量用__block修饰可以让写操作生效.


__block int a = 0;

void (^foo)(void) = ^ {

a = 1;

}

foo();  //此时a的值被修改为1;


后台运行


使用block的另一个用处就是可以让程序在后台叫长久的运行,

在应用按Home键之后 应用可以调用UIApplication的beginBackgroundTaskWithExpirationHandler方法,让应用有最多十分钟的时间在后台长久的运行.这个时间可以用来做清理本地缓存.发送统计数据等工作.

//  AppDelegate.h


@property(assign,nonatomic)UIBackgroundTaskIdentifier backgroundUpdateTask;


//  AppDelegate.m


- (void)applicationDidEnterBackground:(UIApplication *)application {

    

    [self beingBackgroundUpdateTask];


//这里填写后台需要运行的代码

    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.

    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.


    [self endBackgroundUpdateTask];



}

-(void)beingBackgroundUpdateTask {


    self.backgroundUpdateTask = [[UIApplication sharedApplication]beginBackgroundTaskWithExpirationHandler:^{

        [self endBackgroundUpdateTask];

    }];

}


-(void)endBackgroundUpdateTask {

    

    [[UIApplication sharedApplication] endBackgroundTask:self.backgroundUpdateTask];

    self.backgroundUpdateTask = UIBackgroundTaskInvalid;

    

}




    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.

    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值