iOS 开发 Objective-C

第八篇:Objective-C 知识回顾Block

2019-11-19  本文已影响0人  望穿秋水小作坊
Block知识点大纲

8.1.基本概念

问题一:什么是 Block?

首先看下这段代码,我们要分析 Block 具体干了些啥,可以从 Block 编译后的代码分析。使用 xcrun -sdk iphonesimulator clang -rewrite-objc BDBlock.m 可以生成 BDBlock.cpp 文件,借助这个文件可以查看 Block 内部干了些啥。

//#import "BDBlock.h"
@implementation BDBlock
- (void)myMethod
{
    int multiplier = 6;
    int(^MyBlock)(int) = ^int(int num) {
        return num * multiplier;
    };
    MyBlock(2);
}
@end

截取其中一段代码

static void _I_BDBlock_myMethod(BDBlock * self, SEL _cmd) {
   int multiplier = 6;
   
   /*
    int(^MyBlock)(int) = ^int(int num) {
        return num * multiplier;
    };
    */
   int(*MyBlock)(int) = ((int (*)(int))&__BDBlock__myMethod_block_impl_0((void *)__BDBlock__myMethod_block_func_0, &__BDBlock__myMethod_block_desc_0_DATA, multiplier));
   
   /*
    MyBlock(2);
    */
   ((int (*)(__block_impl *, int))((__block_impl *)MyBlock)->FuncPtr)((__block_impl *)MyBlock, 2);
}
问题二:Block 调用的本质是什么?

8.2.Block 对变量的截获

问题三:请回答 Block 对下面的变量截获都有什么异同?
请回答 Block 对下面的变量截获都有什么异同?
- (void)myMethod2
{
    //基本数据类型的局部变量
    int var = 1;
    //对象型的局部变量
    __unsafe_unretained id unsafe_obj = nil;
    __strong id strong_obj = nil;
    
    //局部静态变量
    static int static_var = 3;
    void(^Block)(void) = ^ {
        NSLog(@"局部变量<基本数据类型> var %d", var);
        
        NSLog(@"局部变量<__unsafe_unretained 对象类型> var %@", unsafe_obj);
        NSLog(@"局部变量<__strong 对象类型> var %@", strong_obj);
        
        NSLog(@"静态局部变量 %d", static_var);
        
        NSLog(@"全局变量 %d", global_var);
        NSLog(@"全局静态变量 %d", global_static_var);
    };
    
    Block();
}

这段代码被编译的代码可以用命令 xcrun -sdk iphonesimulator clang -rewrite-objc -fobjc-arc BDBlock.m 来生成 cpp 文件查看。

static void _I_BDBlock_myMethod2(BDBlock * self, SEL _cmd) {

    int var = 1;

    __attribute__((objc_ownership(none))) id unsafe_obj = __null;
    __attribute__((objc_ownership(strong))) id strong_obj = __null;


    static int static_var = 3;
    void(*Block)(void) = ((void (*)())&__BDBlock__myMethod2_block_impl_0((void *)__BDBlock__myMethod2_block_func_0, &__BDBlock__myMethod2_block_desc_0_DATA, var, unsafe_obj, strong_obj, &static_var, 570425344));

    ((void (*)(__block_impl *))((__block_impl *)Block)->FuncPtr)((__block_impl *)Block);
}

从编译后的代码可以看出

8.3. __block 修饰符

问题四:请问下面代码能正常运行吗?是否需要 __block 关键字的协助?
    NSMutableArray *array = [[NSMutableArray alloc] init];
    void(^Block)(void) = ^ {
        [array addObject:@"111"];
    };
    [array addObject:@"222"];
    NSLog(@"%@",array);
    Block();
    NSLog(@"%@",array);
问题五:请问下面代码能正常运行吗?是否需要 __block 关键字的协助?
    NSMutableArray *array = nil;
    void(^Block)(void) = ^ {
        array = [NSMutableArray new];
    };
    [array addObject:@"222"];
    NSLog(@"%@",array);
    Block();
    NSLog(@"%@",array);
问题六:请回答什么情况下会使用到 __block 修饰符?
问题七:请回答对哪些变量在 Block 代码块里面赋值需要添加 __block 修饰词?
问题八:请回答对哪些变量在 Block 代码块里面赋值不需要添加 __block 修饰词?
问题九:思考如下代码的输出?
    __block int multiplier = 6;
    int(^Block)(int) = ^int(int num) {
        return num * multiplier;
    };
    multiplier = 4;
    NSLog(@"Result is %d",Block(2));
问题十:思考 __block 修饰基本数据类型,对基本数据类型做什么事情?

8.4.Block 的内存管理

问题一:思考 __block 在内存方面有哪几种类型?
三种 Block 在内存存储位置
问题二:思考我们在对 Block 进行 copy 操作会产生什么效果?
对 Block 进行 copy 的结果
问题三:思考我们在何时需要对 Block 进行 copy 操作?
栈上的 block 如果不 copy 会随着作用域的结束,而被释放
问题四:思考既然栈上的__forwarding指向自己,为什么还需要呢?

8.5.Block 的循环引用问题

问题一:思考下面的代码存在什么问题?如何解决?
    _mutableArray = [NSMutableArray arrayWithObject:@"block"];
    _blk = ^NSString*(NSString* num) {
        return [NSString stringWithFormat:@"%@", _mutableArray[0]];
    };
    _blk(@"hello");
    // 解决方案
    _mutableArray = [NSMutableArray arrayWithObject:@"block"];
    __weak NSArray *weakArray = _mutableArray;
    _blk = ^NSString*(NSString* num) {
        return [NSString stringWithFormat:@"%@", weakArray[0]];
    };
    _blk(@"hello");
问题一:思考下面的代码存在什么问题?如何解决?
__block ViewController* blockSelf = self;
    _blk = ^NSString*(NSString* num) {
        return [NSString stringWithFormat:@"%@", blockSelf.mutableArray[0]];
    };
    _blk(@"hello");
    __block ViewController* blockSelf = self;
    _blk = ^NSString*(NSString* num) {
        NSString* temp = [NSString stringWithFormat:@"%@", blockSelf.mutableArray[0]];
        blockSelf = nil;
        return temp;
    };
    _blk(@"hello");
上一篇 下一篇

猜你喜欢

热点阅读