开发者iOS过坑技巧iOS Foundations

IOS开发-block分析

2015-12-15  本文已影响2164人  没阳光的午后

block的定义

// 无参无返回
void(^block)();
// 无参有返回
int(^block1)();
// 有参有返回
int(^block1)(int number);

也可以直接打入inline来自动生成block格式

<#returnType#>(^<#blockName#>)(<#parameterTypes#>) = ^(<#parameters#>) {
        <#statements#>
    };

block的循环引用

__weak typeof(self) weakSelf = self;
__strong typeof(self) strongSelf = weakSelf;

block的内存管理

通过block来传值

在前一个控制器的touchesBegan:方法内实现如下代码


    ModalViewController *modalVc = [[ModalViewController alloc] init];
    
    modalVc.valueBlcok = ^(NSString *str){
        
        NSLog(@"ViewController拿到%@",str);
    };
    
    [self presentViewController:modalVc animated:YES completion:nil];

**在ModalViewController控制器的.h文件中声明一个block属性 **@property (nonatomic ,strong) void(^valueBlcok)(NSString *str);

并在.m文件中实现方法


- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    // 传值:调用block
    if (_valueBlcok) {
        _valueBlcok(@"123");
    }
}

这样在ModalViewController回到上一个控制器的时候,上一个控制器的label就能显示ModalViewController传过来的字符串

block作为一个参数使用

新建一个类,在.h文件中声明一个方法- (void)calculator:(int(^)(int result))block;

并在.m文件中实现该方法

- (void)calculator:(int (^)(int))block
{
    self.result = block(self.result);
}

在其他类中调用该方法

    CalculatorManager *mgr = [[CalculatorManager alloc] init];
    [mgr calculator:^(int result){
        result += 5;
        return result;
    }];

block作为返回值使用

masonry框架中我们可以看到如下用法make.top.equalTo(superview.mas_top).with.offset(padding.top); 这个方法实现就是将block作为返回值来使用

来分析一下这段代码
其实可以将这段代码看成make.top,make.equalTo,make.with,make.offset,所以可以得出一个结论是make.top返回了一个make,才能实现make.top.equalTo

**那来模仿一下这种功能的实现** 新建一个类,在.h文件中声明一个方法- (CalculatorManager *(^)(int a))add;```

.m文件中实现方法

- (CalculatorManager * (^)(int a))add
{
    return ^(int a){
        _result += a;
        return self;
    };
}

这样就可以在别的类中实现上面代码的用法

mgr.add(1).add(2).add(3);

block的变量传递

验证一下是不是这样
通过Clang来将main.m文件编译为C++
在终端输入如下命令clang -rewrite-objc main.m

void(*block)() = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_a_0 *)&a, 570425344));
void(*block)() = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, a));

可以看到在编译后的代码最后可以发现被__block修饰过得变量使用的是&a,而局部变量是a

还在学习中,有错误请指出,谢谢!!

上一篇下一篇

猜你喜欢

热点阅读