iOS中block的使用

一、block简介

block代码块是在iOS4开始引入的对C语言的扩展,用来实现匿名函数的特性,block是一种特殊的数据类型,其可以正常定义变量、作为参数、作为返回值,blcok还可以保存一段代码,在需要时调用。

二、block定义

block在定义时并不会执行内部的代码,只有在调用时才会执行。

//block变量的赋值:Block变量 = ^(参数列表){函数体};

1、无参数无返回值的block

//1、无参数无返回值的block
    //zqqBlock是block名 无参数可省略参数列表()
    //void (^zqqBlock)() = ^{};
    void (^zqqBlock)() = ^(){
        NSLog(@"这是无返回值无参数的block");
    };
    //调用
    zqqBlock();

2、有参数无返回值的block

    //zqqBlock是block名 NSString 是参数类型,x,y参数
    void (^zqqBlock)(NSString* ,NSString*) = ^(NSString *x,NSString *y){
        NSLog(@"这是无返回值有参数的block,参数是%@,%@",x,y);
    };
    //调用
    zqqBlock(@"a",@"b");

3、有参数有返回值的block

    //NSString是返回类型 zqqBlock是block名 NSString 是参数类型,x,y参数
    NSString* (^zqqBlock)(NSString* ,NSString*) = ^(NSString *x,NSString *y){
        return [NSString stringWithFormat:@"%@+%@",x,y];
    };
    //调用
    NSString *testStr = zqqBlock(@"a",@"b");
    NSLog(@"%@",testStr);

三、block使用

1、block重命名

利用typedef为block进行重命名

#import "ViewController.h"
@interface ViewController ()
//定义一个无返回值无参数的block
typedef void (^zqqBlock)();
//用自定义的zqqBlock声明一个block
@property (nonatomic, copy) zqqBlock abock;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // 避免循环引用,用__weak修饰
    __weak ViewController *weakSelf = self;
    self.abock = ^{
        weakSelf.view.backgroundColor = [UIColor redColor];
    };
    //调用
    self.abock();
}
@end

2、block的应用场景

block声明属性要用copy修饰
因为只有copy后的Block才会在堆中,栈中的Block的生命周期是和栈绑定的
<栈 :由系统维护的局部变量 是存在栈上的,其生命周期随函数的生命周期>
<堆 :由程序员申请空间地址,由程序员手动释放,生命周期受到程序员控制>
使用retain也可以,因为block的retain行为默认是用copy的行为实现的,block变量默认是声明为栈变量的,为了能够在block的声明域外使用,所以要把block拷贝(copy)到堆,所以说为了block属性声明和实际的操作一致,最好声明为copy。

block的使用:
  • 反向传值
//1.在NextViewController.h中声明block
#import <UIKit/UIKit.h>
typedef void (^popToNextBlock)(UIColor *color);//1.别名 传参
@interface NextViewController : UIViewController
@property (nonatomic, strong) popToNextBlock popToNextBlock;//2.声明block
@end
//2.在NextViewController.m中定义block
#import "NextViewController.h"
-(void)popToFirstBtnClick:(id)sender{
    [self.navigationController popViewControllerAnimated:YES];
    if (self.popToNextBlock){
        UIColor *color = [UIColor redColor];
        self.popToNextBlock(color);
    }
}
//上一控制器push时调用
    NextViewController *nextVc = [[NextViewController alloc]init];
    [self.navigationController pushViewController:nextVc animated:YES];
    //调用block
    __weak ViewController *weakSelf = self;
 //block的回调只对最后一次赋值有效
    nextVc.popToNextBlock = ^(UIColor *color){
        //避免循环引用,应该使用弱引用
          weakSelf.view.backgroundColor = color;
    };
  • 在方法中定义block 回调传值
//1.ZqqTool.h文件
#import <Foundation/Foundation.h>
typedef void(^ZqqToolBlock)(NSString *string);
@interface ZqqTool : NSObject
//在方法中封装block
-(void)zqqToolWithString:(NSString *)str andBlock:(ZqqToolBlock)block;
//2.ZqqTool.m文件
#import "ZqqTool.h"
-(void)zqqToolWithString:(NSString *)str andBlock:(ZqqToolBlock)block{
    block(str);
}
@end
//3.调用
    ZqqTool *tool = [[ZqqTool alloc]init];
    [tool zqqToolWithString:@"测试" andBlock:^(NSString *string) {
        NSLog(@"%@",string);
    }];
  • 作为参数传递
//1.ZqqSendBlock ZqqTool.h文件
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
typedef void(^ZqqSendBlock)(UIColor *color);
typedef void(^ZqqToolBlock)(NSString *string);
@interface ZqqTool : NSObject
//在方法中封装block
-(void)zqqToolWithString:(NSString *)str andBlock:(ZqqToolBlock)block;
-(void)ZqqSendBlock:(ZqqSendBlock)block;
@end
//2..ZqqTool.m文件
#import "ZqqTool.h"
@implementation ZqqTool
-(void)zqqToolWithString:(NSString *)str andBlock:(ZqqToolBlock)block{
    block(str);
}
-(void)ZqqSendBlock:(ZqqSendBlock)block{
    block([UIColor redColor]);
}
@end
//3.调用
ZqqTool *tool = [[ZqqTool alloc]init];
    [tool zqqToolWithString:@"测试" andBlock:^(NSString *string) {
        NSLog(@"%@",string);
    }];
    [tool ZqqSendBlock:^(UIColor *color) {
        //
        self.view.backgroundColor = color;
    }];
注意:1、block中使用局部变量

局部变量在block中只读。变量的值在Block外改变,也不影响他在Block中的值。局部变量加__block修饰可在block代码块内被修改。

注意:2、block中循环引用问题

block用copy修饰,在self持有block中调用self或调用属于self的都会出现循环引用!解决方法:__weak Class *weakSelf = self;
而block本身不被self持有,就不会出现循环引用了。例如:UIView的动画block

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

推荐阅读更多精彩内容