block 的使用 (一)

iOS 三大回调方式:目标动作回调,委托回调,代码块回调,喜欢 block 是因为他很简洁紧凑,代码可读性高。

block 格式


block 简单操作

无返回值无参数

void(^block)(void) = ^{
    NSLog(@"Hello, World!");
};
        
block(); // 调用方式

无返回值有参数

void(^block)(int) = ^(int value){
    NSLog(@"小狗%d个月大了",value);
};
block(6);

Block[22835:1629584] 小狗6个月大了

无返回值多参数

void(^block)(NSString *,int) = ^(NSString *name, int number){
    NSLog(@"%@已经%d个月大了",name,number);
};
block(@"猫猫",3);

Block[22902:1635602] 猫猫已经3个月大了

有返回值多参数

NSString *(^block)(NSString *,int) = ^(NSString *name, int number){
    return [NSString stringWithFormat:@"%@已经%d个月大了",name,number];
};
NSLog(@"%@",block(@"猫猫",3));

Block[22933:1639591] 猫猫已经3个月大了
block 还有一个功能,捕获变量的能力。
int b = 6;
        
void(^add)(int) = ^(int a){
    NSLog(@"%d",a + b);
};
add(10);

Block[23038:1657584] 16

但是在示例当中代码块里面只能获取,不能改变 b 的值,不然会报错。

想要在代码块里面改变值,只需要在 声明变量前加一个前缀 __block ,就可以了。

__block int b = 6;
        
void(^add)(int) = ^(int a){
    b = b + a;
};  
add(10);
NSLog(@"b = %d",b);

Block[23165:1673618] b = 16

原因:在未加前缀之前,block 传递的是 b 的值,添加前缀后而是把 b 的地址传过去了,所以在block内部便可以修改到外面的变量了。

还可以用 typedef 声明 block。
#import <Foundation/Foundation.h>

typedef void(^Block)(NSString *text);

@interface Person : NSObject

@property (nonatomic, copy) Block block;

@property (nonatomic, copy) NSString *name;

- (void)callYouBack;

@end

#import "Person.h"

@implementation Person

- (void)callYouBack {
    // 判断是否初始化了 block, 不然会奔溃
    if (self.block) {
        self.block(@"回电话");
    }
}

- (void)dealloc {
    NSLog(@"释放%@",self);
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {

        Person *p = [[Person alloc] init];
        // 初始化 block
        p.block = ^(NSString *text) {
            NSLog(@"text = %@",text);
        };
        [p callYouBack];
        
    }
    return 0;
}

Block[23476:1713267] text = 回电话
Block[23606:1724744] 释放<Person: 0x10043c1e0>

有个需求需要在代码块里面,给 p 类中的 name 赋值。

Person *p = [[Person alloc] init];
// 初始化 block
p.block = ^(NSString *text) {
    NSLog(@"text = %@",text);
    p.name = @"张三";
};
 [p callYouBack];

Block[23476:1713267] text = 回电话

程序执行完,发现一个问题! p 类没有释放掉内存。
这里面是因为循环引用了,p 持有了 block,而 block 又持有了 p。所以才释放不了。
解决方式: weak 弱引用

Person *p = [[Person alloc] init];
// 创建 block
__weak typeof(p) weakP = p;
p.block = ^(NSString *text) {
    NSLog(@"text = %@",text);
    weakP.name = @"张三";
};
[p callYouBack];

Block[23606:1724744] text = 回电话
Block[23606:1724744] 释放<Person: 0x10043c1e0>

https://www.zhihu.com/question/30779258

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容