iOS Block完全使用指南

1、Block的声明

格式:

返回值 (^Block名称) (参数类型);

举例:

    //无参无返回值的Block
    void (^Block01)();

    //有参无返回值的Block
    void (^Block02)(int);

    //无参有返回值的Block
    int (^Blcok03)();

    //有参有返回值的Block
    int (^Blcok04)(NSString*, NSString *);

2、Block的定义

格式:

  返回值类型 (^Block名称) (参数类型) = ^(参数) {
         代码体
    };

举例:

//定义无参无返回值的Block
void (^Block01)() = ^(){
        NSLog(@"无参无返回值的Block");
    };

//定义有参无返回值的Block
void (^Block02)(NSString *) = ^(NSString * name) {
        NSLog(@"%@",name);
    };

//定义有返回值无参Block(如果没有参数,=后面()可以省略)
int (^Block03) () = ^() {   
        return 88;
    };

//定义有参有返回值的Block
int (^Block04)(int,int) = ^(int a, int b) {
        return a + b;
    };

Tips:快速生成Block定义:在方法体内输入inlineBlock,选中提示,就会自动生成

3、Block的调用

    //调用无参无返回值Block
    Block01();
    
    //调用有参无返回值Block
    Block02(@"lee");
    
    //调用无参有返回值Block
    int a = Block03();
    
    //调用有参有返回值Block
    int b = Block04(66,88);

4、Block使用场景

  • 保存代码
  • 在一个方法中定义,在另一个方法中使用
    • 这样就需要将Block声明为成员属性
方法1:
@property (nonatomic,strong) int (^Block)(int ,int);      //Block怎么声明就怎么定义成属性
                                    -
方法2:给Block类型起个别名
typedef void (^BlockType) ();         //BlockType:Block类型(有无参数无、有返回值等等)
@property (nonatomic,strong) BlcokType block;
  • 然后给成员属性赋值
self.Block = ^(int a, int b) {
        return a + b;
    };
  • 在别的方法中直接调用成员属性的Block即可
NSLog(@"%d",self.Block(66,88));

  • 在一个类中定义,在另一个类中使用(常用传值)

需求:A控制器跳转到B控制器,当点击B控制器view的时候,让B控制器传一个字符串回A,并dismiss B控制器

- 第一步:在B控制器声明一个Block属性
/** Block属性 */
@property(nonatomic,strong) void (^ Block) (NSString *);
  • 第二步:在跳转到B控制器之前,给B控制器的Block属性赋值(定义B控制器的Block)
//点击按钮跳转到下一个控制器
-(IBAction)nextVCButtonClick
{   
        LGTestVC * testVC = [[LGTestVC alloc] init];
        testVC.Block = ^(NSString * name,UIViewController * VC){
            NSLog(@"%@",name);
            [VC dismissViewControllerAnimated:YES completion:nil];
        };
        [self presentViewController:testVC animated:YES completion:nil];
}
  • 在B控制器调用Block即可传值(做事情)
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    if (_Block != nil)
    {
        _Block(@"lee",self);
    }
}

  • 作为方法参数使用

注意:Block当做参数来使用,并不是马上调用;要在Block做什么事情由外部决定,什么时候做事情由方法内部决定。举个比较常用的例子:

    self.view.transform = CGAffineTransformMakeScale(0.5, 0.5);
    [UIView animateWithDuration:1 animations:^{
        [self.view layoutIfNeeded];
    }];
  • 作为方法返回值使用(多用于框架封装)

Blcok作为返回值使用多用于框架封装,比较典型的一个例子就是:Masnoary, 最大的特点就是可以很方便的使用点语法,也就是链式编程。具体的Block作为返回值使用请参考摩卡奇童鞋的这篇文章 ,在此不再赘述

5、Block内存管理

  • MRC:
  • 如果Block没有引用外部局部变量,Block就保存在内存的全局区
  • 如果Block引用了外部局部变量,Block就保存在内存的栈内存区

  • Block只能使用copy,不能使用retain(使用retain还是保存在栈里面,会被销毁)

    注意:block可以访问局部变量,但是不能修改.如果想要修改局部变量,需要在变量前加__block

  • ARC

  • 如果Block没有引用外部局部变量,Block就保存在内存的全局区
  • 只要Block引用了外部局部变量,Block就保存在堆内存中
  • Block最好不要使用copy,应该使用strong

6、解决循环引用

Block循环引用原因:Block会对里面所有外部局部变量(强指针变量)进行一次强引用,从而导致循环引用。

//需要将外部的强指针变量弱化

__weak typeof(self) weakSelf = self;

_block = ^{
        
        NSLog(@"%@",weakSelf);
        
    };

如果Block里面有非即时操作(延时操作),由于Block内部是弱指针指向,当{}结束之后就被销毁,从而导致延时操作没办法执行,需要在Block内部将弱化的指针再变为强指针

__weak typeof(self) weakSelf = self;

_block = ^{
        
        NSLog(@"%@",weakSelf);

       //将已经弱化的self指针,转换为强指针以便进行延时操作,否则就执行不到延时操作
        __strong typeof(weakSelf) strongSelf = weakSelf;
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            
            NSLog(@"%@",strongSelf);
        });
        
    };

Tips:以下4种情况打印结果分别是多少?

情况1:
- (void)viewDidLoad
{
    [super viewDidLoad];
    
    int a = 3;
    void (^ block)() = ^{ 
        NSLog(@"%d",a);   
    };
    a = 5;

    block();
}
————————————————————————————————————
情况2:
- (void)viewDidLoad
{
    [super viewDidLoad];
    
   static int a = 3;                    ***区别点:静态变量***
    void (^ block)() = ^{ 
        NSLog(@"%d",a);   
    };
    a = 5;

    block();
}
————————————————————————————————————
情况3:
- (void)viewDidLoad
{
    [super viewDidLoad];
    
   __block int a = 3;                    ***区别点:被__block修饰***
    void (^ block)() = ^{ 
        NSLog(@"%d",a);   
    };
    a = 5;

    block();
}
————————————————————————————————————
情况4:
 __block int a = 3;                      ***区别点:全局变量***

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    void (^ block)() = ^{ 
        NSLog(@"%d",a);   
    };
    a = 5;

    block();
}

总结:

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

推荐阅读更多精彩内容