zoukankan      html  css  js  c++  java
  • iOS 面试全方位剖析 -- Block篇

      1.Block的本意

    block本质上也是一个OC对象,它内部也有个isa指针,
    block是封装了函数调用以及函数调用环境的OC对象,
    block是封装函数及其上下文的OC对象

     2.block截获变量

    #import "SYDBlcok.h"
    // 全局变量----不截获全局变量
    int global_var = 4;
    // 静态全局变量-----不截获全局静态变量
    static int static_global_var = 5;
    
    @implementation SYDBlcok
    -(void)method {
        // 基本数据类型的局部变量----只截获值
        int var = 6;
        // 对象类型的局部变量----连同所有修饰符一起截获
        __unsafe_unretained id unsafe_ibject = nil;
        __strong id strong_obj = nil;
        // 局部静态变量---以指针形式截获局部静态变量
        static int multiplier_static = 3;
        NSLog(@"multiplier_static:%d",multiplier_static);
        int(^Block)(int) = ^(int num) {
            NSLog(@"局部变量>基本数据类型:%d",var);
            NSLog(@"局部变量>对象类型%@----strong:%@",unsafe_ibject,strong_obj);
            NSLog(@"局部static:%d",multiplier_static);
            NSLog(@"全局变量%d",global_var);
            NSLog(@"静态全局变量:%d",static_global_var);
            return num * multiplier_static;
        };
        NSLog(@"判断执行顺序");
        // 局部静态变量  -----isa指针
        multiplier_static = 4;
        NSLog(@"result is %d",Block(2));
    }

    编译后结果

    2019-04-16 14:59:38.854104+0800 auditionTest[64047:1220987] viewDidLoad
    2019-04-16 14:59:42.067785+0800 auditionTest[64047:1220987] multiplier_static:3
    2019-04-16 14:59:42.067970+0800 auditionTest[64047:1220987] 判断执行顺序
    2019-04-16 14:59:42.068081+0800 auditionTest[64047:1220987] 局部变量>基本数据类型:6
    2019-04-16 14:59:42.068182+0800 auditionTest[64047:1220987] 局部变量>对象类型(null)----strong:(null)
    2019-04-16 14:59:42.068276+0800 auditionTest[64047:1220987] 局部static:4
    2019-04-16 14:59:42.068366+0800 auditionTest[64047:1220987] 全局变量4
    2019-04-16 14:59:42.068459+0800 auditionTest[64047:1220987] 静态全局变量:5
    2019-04-16 14:59:42.068563+0800 auditionTest[64047:1220987] result is 8

     cpp文件解析

    • FuncPtr:指向调用函数的地址
    • __main_block_desc_0 :block描述信息
    • Block_size:block的大小

         3. block修饰符

        

    /**
     修饰符的使用----对被截获变量进行赋值操作的时候
     */
    -(void)block_property {
        __block NSMutableArray *array = nil;
    //    static、static global或者global变量 不需要添加__block
        void(^block)(void) = ^{
            // 使用array 初始化
            array = [NSMutableArray array];
            [array addObject:@"123"];
        };
        block();
        NSLog(@"array:%@",array);
    }
    // 赋值操作不需要修饰符
    -(void)block_property {
        NSMutableArray *array = [NSMutableArray array];
    // static、static global或者global变量 不需要添加__block

    void(^block)(void) = ^{

    // 使用array 初始化
    array = [array addObject:@"123"];
    };
    block();
    NSLog(@"array:%@",array);
    }

     4.循环引用

    // 循环引用
    -(void)aroundBlock {
        
        _array = [NSMutableArray arrayWithObject:@"block"];
    //    __weak NSArray *weakArray = _array;
    //    kWeakSelf(_array);
        NSString*(^strBlock)(NSString *str) = ^(NSString *num) {
            return [NSString stringWithFormat:@"hello_%@",_array[0]];
    //        return [NSString stringWithFormat:@"hello_%@",weak_array[0]];
        };
        // self z持有block, block有成员变量 array,持有self
        strBlock(@"eden");
    }
    
    -(void)aroundBlock {
        
        _array = [NSMutableArray arrayWithObject:@"block"];
    //    __weak NSArray *weakArray = _array;
        kWeakSelf(_array);
        NSString*(^strBlock)(NSString *str) = ^(NSString *num) {
    //        return [NSString stringWithFormat:@"hello_%@",_array[0]];
            return [NSString stringWithFormat:@"hello_%@",weak_array[0]];
        };
        // self z持有block, block有成员变量 array,持有self
        strBlock(@"eden");
    }
    // weakself 配合strongSelf 使用,防止在block执行的时候self提前突然被释放,也有可能闪退
        __weak __typeof__(self) weakself = self;
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            __strong __typeof(self) strongself = weakself;
            [strongself doSomething];
            [strongself doOtherthing];
        });
    }
    -(void)doSomething {
        NSLog(@"doSomething");
    }
    -(void)doOtherthing{
        NSLog(@"doOtherthing");
    }
    block本身是像对象一样可以retain,和release。但是,block在创建的时候,它的内存是分配在栈(stack)上,而不是在堆(heap)上。他本身的作于域是属于创建时候的作用域,一旦在创建时候的作用域外面调用block将导致程序崩溃。
    使用retain也可以,但是block的retain行为默认是用copy的行为实现的,因为block变量默认是声明为栈变量的,为了能够在block的声明域外使用,所以要把block拷贝(copy)到堆,所以说为了block属性声明和实际的操作一致,最好声明为copy。
  • 相关阅读:
    java+opencv实现图像灰度化
    java实现高斯平滑
    hdu 3415 单调队列
    POJ 3368 Frequent values 线段树区间合并
    UVA 11795 Mega Man's Mission 状态DP
    UVA 11552 Fewest Flops DP
    UVA 10534 Wavio Sequence DP LIS
    UVA 1424 uvalive 4256 Salesmen 简单DP
    UVA 1099 uvalive 4794 Sharing Chocolate 状态DP
    UVA 1169uvalive 3983 Robotruck 单调队列优化DP
  • 原文地址:https://www.cnblogs.com/edensyd/p/10716629.html
Copyright © 2011-2022 走看看