Block总结

来源:互联网 发布:淘宝上的开团提醒 编辑:程序博客网 时间:2024/05/16 05:55

block小结

定义:

1 Block是C语言的

2 Block是一个数据类型

3 是一个提前准备好的代码,在需要的时候执行

/** Block是C语言的 Block是一个数据类型 是一个提前准备好的代码,在需要的时候执行 */void demoBlock1();void demoBlock2();void demoBlock3();int main(int argc, const char * argv[]) {    @autoreleasepool {        demoBlock3();    }    return 0;}void demoBlock3() {       // 指针记录的是地址    NSMutableString *strM = [NSMutableString stringWithString:@"zhangsan"];    NSLog(@"定义前 %p %p", strM, &strM);       void (^myBlock)() = ^ {        // 修改strM指针指向的内容        [strM setString:@"lisi"];        NSLog(@"inblock %p %p", strM, &strM);               // 这句代码是修改strM指针指向的地址//        strM = [NSMutableString stringWithString:@"wangwu"];    };    NSLog(@"定义后 %p %p", strM, &strM);       myBlock();    NSLog(@"%@", strM);}void demoBlock2() {    // 使用 __block,说明不在关心x数值的具体变化    __block int x = 10;    NSLog(@"定义前 %p", &x);                 // 栈区       // 如果要在block中,修改外部变量的数值,需要使用 __block 修饰符号    // 定义block时,如果引用了外部使用__block的变量,block定义之后,外部变量的指针地址同样会变成堆区的地址    void (^myBlock)() = ^ {        x = 80;        NSLog(@"in block %p", &x);          // 堆区    };    NSLog(@"定义后 %p", &x);                 // 堆区       myBlock();    NSLog(@"%d", x);}
</pre><pre code_snippet_id="1656895" snippet_file_name="blog_20160421_3_7967570" name="code" class="objc">void demoBlock1() {    int x = 10;    NSLog(@"定义前 %p", &x);                 // 栈区       // 提问:输出是多少?    // 在定义block的时候,如果引用了外部变量,会对外部变量做一个copy,记录住定义block时变量的数值    // 如果后续再修改x的值,不会影响block内部的数值变化!    // 在默认情况下,不允许block内部修改外部变量的数值!因为会破坏代码的可读性,不易于维护!    void(^myBlock)() = ^ {        //        x = 80;               NSLog(@"%d", x);        NSLog(@"in block %p", &x);          // 堆中的地址    };       NSLog(@"定义后 %p", &x);                 // 栈区    x = 20;       myBlock();}// block的定义void demo() {    // block定义的速记符号    // inlineblock,能够快速敲出一个block的基本结构    // 提示:block的定义必须要过关!    // 如果记不住,可以用inlineblock辅助记忆,不要依赖inlneblock       // 定义block    /**     定义时,把block当成数据类型         特点:     1. 类型比函数定义多了一个 ^     2. 设置数值,有一个 ^,内容是 {} 括起的一段代码         最简单的定义方式     void (^myBlock)() = ^ { // 代码实现; }     */    void (^myBlock)() = ^ {        NSLog(@"hello");    };       // 执行时,把block当成函数    myBlock();       // 定义带参数的block    // 格式:void (^block名称)(参数列表) = ^ (参数列表) { // 代码实现; }    void (^sumBlock)(int, int) = ^ (int x, int y) {        NSLog(@"%d", x + y);    };       sumBlock(10, 20);       // 定义带返回值的block    // 格式:返回类型 (^block名称)(参数列表) = ^ 返回类型 (参数列表) { // 代码实现; }    int (^sumBlock2)(int, int) = ^ int (int a, int b) {        return a + b;    };       NSLog(@"%d", sumBlock2(4, 8));}



// 如果要将block当作返回值,需要先单独定义一下block的类型// 速记符号:typedefBlocktypedef void(^workBlock)();使用block进行排序,效率非常高,以后替换掉for循环      // 1. 从iOS4开始,苹果封装了一系列块代码简化操作,提高效率    // 1> 使用块代码遍历,效率比for in要高    // 2> 把循环所需要的所有素材都以参数的形式提供了,可以直接使用    [array enumerateObjectsUsingBlock:^(NSNumber *num, NSUInteger idx, BOOL *stop) {        NSLog(@"%@", num);               if (idx == 3) {            *stop = YES;        }    }];排序(效率比正常排还要高) NSArray *result = [array sortedArrayUsingComparator:^NSComparisonResult(NSNumber *num1, NSNumber *num2) {//             compare 可以比较NSString,NSDate,NSNumber...            // 升序            return [num1 compare:num2];            // 降序            return [num2 compare:num1];                       // 乱序,随机的顺序=》一会升序,一会降序            int seed = arc4random_uniform(2);            if (seed == 1) {                // 升序                return [num1 compare:num2];            } else {                return [num2 compare:num1];            }        }];







注意点: 

一.   block的反向传值
 
 1.
调用方:准备块代码
   
"代理"来对比-类似于协议方法的实现
   
不同点:块代码都在一起,并没有单独的实现一个方法
 
 2.
被调用方:执行块代码
 1>    
要执行的代码:在.h中定义一个块代码的属性,又被称作回调方法
 2>    
在需要的时候执行块代码!

 



  • 1 定义一个块代码的属性,block属性需要用copy
@property(nonatomic,copy)void(^completion)(NSString*text);
  • 2 给目标视图控制器传值(准备执行的块代码)
    // 目标视图控制器
    CZEditViewController *vc = segue.destinationViewController;
    vc.completion= ^ (NSString*str) {
       
self.nameLabel.text= str;
    };
  • 3 在执行之前,先判断块代码属性是否有内容
    if (self.completion) {
       
self.completion(self.nameText.text);
    }



block陷阱

block的陷阱-有可能会出现循环引用
 
 
解决办法:
 1.
要对内存对象之间的引用关系要清楚
 
技巧:
 1.
block中碰到self,要格外小心,有可能会出现循环引用,通常最好思考一下
 2.
利用dealloc协助判断!如果不能被正常释放就说明有循环引用!
 

 *** block在反向传值上有什么特点?
 
-简单
 
-所有代码都在一起,便于阅读,便于维护
 
 *** block & delegate
如何选择?
 
 
-如果回调方法比较少,12,最好不要超过3个,这个时候使用block比较合适
 
-如果回调方法太多,会让代码显得臃肿,反而不好维护
 
 
-如果回调方法非常多,同时又不用每一个方法都必须实现,这个时候用delegate会比较方便!
 

0 0
原创粉丝点击