Block常见使用总结(传值/作为参数/作为返回值等)

来做个block的笔记。

  • block定义
  • block类型
  • block传值
  • block作为参数的方法定义与调用
  • block作为返回值
    (如果嫌文章太长想直接看代码的可以点这里block练习总结demo

block定义

block:带有自动变量(局部变量)的匿名函数。
在xcode里直接输入 inline就会出现block的具体书写格式
block格式:返回值类型(^block的名字)(参数类型) = ^(参数类型和参数名) {};
returnType(^blockName)(parameterTypes) = ^(parameters) { statements };
格式里的返回值可以为空、参数类型可以为空、参数类型和参数名也可以为空。

block类型

  • 1.没有返回值,没有参数的block
// 没有返回值,没有参数的定义方式
    void(^myBlock_1)() = ^{
        NSLog(@"mymyBlock_111");
    };
    myBlock_1(); // 调用block
    ->运行结果 “mymyBlock_111”
  • 2.没有返回值,有参数的block
// 没有返回值,两个参数为int,必须要写参数,而且必须要有参数变量名
    void(^myBlock_2)(int, int) = ^(int a, int b){
        int c = a + b;
        NSLog(@" a + b = %d", c);
    };
    myBlock_2(2 ,3); // 调用
    // ->运行结果“a + b = 5”
  • 3.带返回值、参数的block
// 带有返回值与参数 返回值int 参数为int
    int(^myBlock_3)(int) = ^(int d){
        return d * d;
    };
    int result = myBlock_3(6);
    NSLog(@" 运算结果 = %d",result);
    // ->运行结果“运算结果 = 36”
  • 4.定义block类型
 定义block的类型:
格式就是 返回值(^)(参数类型)
typedef void(^wxkBlock)(NSString * valueStr);  // wxkBlock不是变量名,而是这种类型的block的别名
@interface ViewController : UIViewController
@property (nonatomic, copy) wxkBlock wBlcok; //由上面wxkBlock创建,这样在类中可以拿到self.wBlcok
@end 
//也可以这样定义
@interface ViewController : UIViewController
@property (nonatomic, copy) void(^xkBlock)(NSString * valueStr); //这样在类中可以拿到self.xkBlock
@end

block传值

第一个控制器为ViewController
第二个控制器为BlockPassByValueVC
我们从 ViewController 跳入 BlockPassByValueVC ,然后从BlockPassByValueVC 跳回第一个页面,顺便传个值给 ViewController (反向传值)
在ViewController 打印传过来的值

// 在 BlockPassByValueVC 的.h文件里定义block(和使用delegate差不多)
#import <UIKit/UIKit.h>

@interface BlockPassByValueVC : UIViewController
// 反向传值的block
@property (nonatomic, copy) void(^passValueBlock)(NSString * valueStr);

@end
// 从ViewController的.m 跳进 BlockPassByValueVC 的点击事件
- (IBAction)exchangeValue:(id)sender
{
    BlockPassByValueVC * BlockPVc = [[BlockPassByValueVC alloc] init];
    /**
     passValueBlock 是 BlockPVc 这样控制器里的 block
     valueStr 为 BlockPVc 控制器要传递过来的参数
     {}括号里的代码是在BlockPVc的.m文件里传了参数运行block的时候才会调用
     */
    BlockPVc.passValueBlock = ^(NSString *valueStr) {
        NSLog(@"传过来的值 = %@",valueStr);
    };
    [self presentViewController:BlockPVc animated:YES completion:nil];
}
// BlockPassByValueVC 的.m文件里传值的点击事件
- (void) touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    if (self.passValueBlock) // 如果在上一个页面调用了这个block,就执行下面的方法
    {
        self.passValueBlock(@"10086"); //把这里的值当参数传递过去
    }
    [self dismissViewControllerAnimated:YES completion:nil];
}
// 在跳回ViewController 的时候 传递的值"10086"就会传到ViewController里
 ViewController的输出的结果为: 传过来的值 = 10086

如果没看明白的话可以看一下我总结的block练习总结demo


block作为参数的方法定义与调用

  • block作为参数 无返回值 无参数(事件完成后调用block块里的方法)
// 定义 在这个方法完成后 再调用其他方法(写在block里的方法)
- (void)block_t_5:(void(^)())finish
{
    NSLog(@"先处理block_t_5方法里的事件");
    // 在调用完此方法处理事件后 调用block块里的方法
    if (finish)
    {
        finish();
    }
}

// 调用方法
    [self block_t_5:^{
        NSLog(@"完成block_t_5事件成功后,在进行其他操作");
    }];

// 方法调用后打印的日志
// log:先处理block_t_5方法里的事件
// log:完成block_t_5事件成功后,在进行其他操作
  • block作为参数 无返回值 参数为NSSstring类型
// 定义  无返回值 参数为NSSstring类型
- (void)block_t_6:(void(^)(NSString * B_str)) finish
{
    NSLog(@"先处理block_t_6方法里的事件");
    if (finish)
    {
        NSString * tempStr = @"block_t_6-10086";
        finish(tempStr);
    }
}

// 调用方法
    [self block_t_6:^(NSString *B_str) {
        NSLog(@"完成block_t_6事件成功后--%@",B_str);
    }];

// 方法调用后打印的日志
// log:先处理block_t_6方法里的事件
// log:完成block_t_6事件成功后--block_t_6-10086
  • block作为参数 无返回值 参数为NSSstring类型,根据另一个方法参数code的值来判断执行不同的block
// 定义  无返回值 参数为NSSstring类型,根据另一个方法参数code的值来判断执行不同的block
- (void)block_t_7:(void(^)(NSString * B_str7))myBlock_7 AndCodeName:(int)code
{
    switch (code) {
        case 1:
        {
            NSLog(@"code等于111时的操作");
            if (myBlock_7)
            {
                myBlock_7(@"11111111");
            }
        }
            break;
        case 2:
        {
            NSLog(@"code等于222时的操作");
            if (myBlock_7)
            {
                myBlock_7(@"222222222");
            }
        }
            break;
        default:
        {
            if (myBlock_7)
            {
                myBlock_7(nil);
            }
        }
            break;
    }
}

// 调用方法
    [self block_t_7:^(NSString *B_str7)
    {
        NSLog(@" -- %@",B_str7);
    }AndCodeName:1]; // 传入方法的code值为1

// 方法调用后打印的日志
// log:code等于111时的操作
// log:11111111

  • block作为参数 返回值为NSString类型 参数为NSString类型
// 定义 返回值为NSString类型 参数为NSString类型
- (void)block_t_8:(NSString *(^)(NSString * B_str8))myBlock_8
{
    //
    NSString * tempStr = @"T_str";
    if (myBlock_8)
    {
        tempStr = myBlock_8(tempStr);
        NSLog(@"tempStr = %@",tempStr);
    }
}

// 调用方法
    [self block_t_8:^NSString *(NSString *B_str8) {
        return [NSString stringWithFormat:@"拼接一句话在传进的参数前 - %@",B_str8];
    }];

// 方法调用后打印的日志
// log:tempStr = 拼接一句话在传进的参数前 - T_str

如果没看明白 可以看一下我总结的block练习总结demo


block作为返回值

参考网上都是以类似计算器数值相加来实现block做返回值的链式编程,类似 Masonry 的调用那样。

一个相加的工具类 MyTool
一个NSObject的类别 NSObject+Tool 定义个类方法 方便调用(也许现在你还不懂为什么创建者两个类,看代码你就明白了)

MyTool类

// MyTool的 .h
@interface MyTool : NSObject

@property (nonatomic, assign) NSInteger result; // 相加的结果

// 返回值为block的方法,block的返回值为这个类的本身,参数为NSInteger
- (MyTool * (^)(NSInteger)) add; 

@end

// MyTool的 .m
@implementation MyTool
- (MyTool * (^)(NSInteger)) add
{
// 返回值为 block
    return ^(NSInteger value){
        _result += value;
        return self;  // block的返回值为它自己本身(为了后面可以持续用“点语法”调用)
    };
}
@end

NSObject+Tool类

NSObject+Tool的.h
@interface NSObject (Tool)
// block做参数的类方法 block的返回值为空 参数为MyTool
+ (NSInteger)wxk_makeTool:(void(^)(MyTool *))block;  
@end

NSObject+Tool的.m
@implementation NSObject (Tool)
+ (NSInteger)wxk_makeTool:(void (^)(MyTool *))block
{
    MyTool * myTool = [[MyTool alloc] init];
    block(myTool); // 调用block MyTool本身作为该block的参数
    return myTool.result; // 返回运算结果
}
@end

方法调用

#import "MyTool.h"
#import "NSObject+Tool.h"

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 链式变成  block做参数 做返回值
    NSInteger  values = [NSObject wxk_makeTool:^(MyTool * tool) {
        tool.add(10).add(20).add(30);
    }];
    
    NSLog(@"values = %ld",(long)values);
}

// log:values = 60

最后这个“block作为返回值” 说的比较模糊,会再更新做调整。
如果没看明白 可以看一下我总结的block练习总结demo

  • 之前我在写block的时候 顺手就把它的修饰写成了strong,关于block要用copy修饰,还是用strong修饰.

block本身是像对象一样可以retain,和release。但是,block在创建的时候,它的内存是分配在栈(stack)上,而不是在堆(heap)上。他本身的作于域是属于创建时候的作用域,一旦在创建时候的作用域外面调用block将导致程序崩溃。
使用retain也可以,但是block的retain行为默认是用copy的行为实现的,因为block变量默认是声明为栈变量的,为了能够在block的声明域外使用,所以要把block拷贝(copy)到堆,所以说为了block属性声明和实际的操作一致,最好声明为copy。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容