简单谈谈Block

 * author:conowen@大钟                                                                                                                          
 * E-mail:conowen@hotmail.com      

1、Block的定义

Block是Objc、C、C++的一个语言级别扩充功能,Block其实就是一块代码段,你可以很方便地把一个代码段传递到不同的方法里面或者不同的类,就像传值一样方便。Block可以当做Objc里面的一个对象。(也就是说,你可以把它当做一个类似NSString的对象)

2、Block的声明

//As a local variable:  
returnType (^blockName)(parameterTypes) = ^returnType(parameters) {...};  

//As a property:  
@property (nonatomic, copy, nullability) returnType (^blockName)(parameterTypes);  

//As a method parameter:  
  
- (void)someMethodThatTakesABlock:(returnType (^nullability)(parameterTypes))blockName;  

//As an argument to a method call:  
[someObject someMethodThatTakesABlock:^returnType (parameters) {...}];  

//As a typedef:  
typedef returnType (^TypeName)(parameterTypes);  
TypeName blockName = ^returnType(parameters) {...};  

上述定义来源

http://fuckingblocksyntax.com/

3、Block声明详解

其实Block的定义有点类似函数指针

引申:指针函数与函数指针的区别

  • a、指针函数
    表示函数返回值是一个指针类型,定义如下
//类型标识符  *函数名(参数表)  
int *fun(x,y);  
  • b、函数指针
    表示指向这个函数的指针变量,定义如下
类型标识符  (*函数名)(参数表)  

int (*fun) (int x,y); //函数名前面有一个星号,然后用小括号包起来  
fun=funTest; /* 将funTest函数的首地址赋给指针  

而Block就是
int (^fun) (int,int);

3、Block的应用场景

3.1、定义一个Block,然后输出打印信息

int (^addFun)(int,int) = ^int(int a,int b){  
  
    return a + b;  
};  
  
NSLog(@"addValue = %d",addFun(1,2));  

打印消息是
2016-06-01 11:27:14.191 Runtime[10910:4558911] addValue = 3

3.2、Block与Delegate的区别

这是最简单的Block使用,一般我们使用Block来做一些有趣的事情,例如代替delegate,平常我们在不同的类传值的话,一般使用delegate,虽然也能实现,但是写法比较繁琐,用Block就能很轻松实现,而且代码量少了不少。
下面的小Demo就依次对比了Delegate与Block在不同类的传值的区别

第一个ViewController的代码如下


//  
//  ViewController.m  
//  Runtime  
//  
//  Created by idealMac2 on 16/5/20.  
//  Copyright © 2016年 GValley. All rights reserved.  
//  
  
#import "ViewController.h"  
#import "SecondViewController.h"  
  
@interface ViewController () <SecondViewControllerDelegate>  
  
@end  
  
@implementation ViewController  
  
- (void)viewDidLoad {  
    [super viewDidLoad];  
    // Do any additional setup after loading the view, typically from a nib.  
      
      
    UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(100, 200, 60.0, 20.0)];  
    [btn setTitle:@"open" forState:UIControlStateNormal];  
    [btn setTitleColor:[UIColor darkGrayColor] forState:UIControlStateNormal];  
    [btn addTarget:self action:@selector(openAction:) forControlEvents:UIControlEventTouchUpInside];  
    [self.view addSubview:btn];  
}  
  
- (void)openAction:(id)sender{  
    NSLog(@"openAction");  
    SecondViewController *secondViewController = [SecondViewController new];  
    secondViewController.callBackValue =  ^ void (NSString *str){  
        NSLog(@"Block str = %@",str);  
       
    };  
    secondViewController.delegate = self;  
    [self presentViewController:secondViewController animated:YES completion:nil];  
  
}  
  
#pragma mark SecondViewControllerDelegate  
- (void)closeAction:(NSString *) str{  
  
    NSLog(@"delegate str = %@",str);  
}  
  
- (void)didReceiveMemoryWarning {  
    [super didReceiveMemoryWarning];  
    // Dispose of any resources that can be recreated.  
}  
  
@end  

第二个ViewController的头文件如下

//  
//  SecondViewController.h  
//  Runtime  
//  
//  Created by idealMac2 on 16/6/1.  
//  Copyright © 2016年 GValley. All rights reserved.  
//  
  
#import <UIKit/UIKit.h>  
//声明delegate  
@protocol SecondViewControllerDelegate <NSObject>  
  
@optional  
- (void)closeAction:(NSString *) str;  
  
@end  
  
@interface SecondViewController : UIViewController  
//声明Block  
@property (nonatomic,copy) void(^callBackValue)(NSString *);  
  
@property (nonatomic,weak) id<SecondViewControllerDelegate>  delegate;  
@end  

第二个ViewController的实现文件如下


//  
//  SecondViewController.m  
//  Runtime  
//  
//  Created by idealMac2 on 16/6/1.  
//  Copyright © 2016年 GValley. All rights reserved.  
//  
  
#import "SecondViewController.h"  
  
@interface SecondViewController ()  
  
@end  
  
@implementation SecondViewController  
  
- (void)viewDidLoad {  
    [super viewDidLoad];  
    // Do any additional setup after loading the view.  
      
    UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(100, 200, 60.0, 20.0)];  
    [btn setTitle:@"close" forState:UIControlStateNormal];  
    [btn setTitleColor:[UIColor darkGrayColor] forState:UIControlStateNormal];  
    [btn addTarget:self action:@selector(closeAction:) forControlEvents:UIControlEventTouchUpInside];  
    [self.view addSubview:btn];  
}  
  
- (void)closeAction:(id)sender{  
  
      
    NSString *strA = @"closed";  
    //Block的方式  
    self.callBackValue(strA);  
      
    //Delegate的方式  
    if (self.delegate && [self.delegate respondsToSelector:@selector(closeAction:)]) {  
        [self.delegate closeAction:strA];  
    }  
     
    [self dismissViewControllerAnimated:YES completion:nil];  
   
}  
  
  
  
  
- (void)didReceiveMemoryWarning {  
    [super didReceiveMemoryWarning];  
    // Dispose of any resources that can be recreated.  
}  
  
/* 
#pragma mark - Navigation 
 
// In a storyboard-based application, you will often want to do a little preparation before navigation 
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 
    // Get the new view controller using [segue destinationViewController]. 
    // Pass the selected object to the new view controller. 
} 
*/  
  
@end  

打印消息如下

2016-06-01 12:10:31.211 Runtime[10959:4573582] block str = closed
2016-06-01 12:10:31.211 Runtime[10959:4573582] delegate str = closed

4、Block与外部变量的关系

我们知道,Block有一个神奇之处,它可以直接使用Block之外的变量,如下面的代码。

int c = 0;  
  
int (^addFun)(int,int) = ^int(int a,int b){  
    return a + b + c;  
};  
NSLog(@"addValue = %d",addFun(1,2));  

但是如果要修改外部变量,就会出现无法修改的问题,同时,使用外部变量,也会存在引起循环引用的问题。

4.1、如何修改Block外部变量

解决这个问题有两种方法:
一种是C语言的方法,因为C语言中的静态变量、静态全局变量,全局变量是允许Block修改其值的。因为“全局变量” 和“ 全局静态变量” 由于作用域是全局,所以在 Block 内访问和读写这两类变量和普通函数没什么区别。但是“ 静态变量” 作用域在 block 之外,那Block是怎么对它进行读写呢?其实“静态变量” 是通过指针传递,将变量传递到 Block 里面,所以可以修改变量值。普通的非全局变量,都是通过传值进去Block里面,当然无法修改这个变量的值。

如下面的代码

static int c = 0;//静态变量  
  
int (^addFun)(int,int) = ^int(int a,int b){  
    c = 1;  
    return a + b + c;  
};  
NSLog(@"addValue = %d",addFun(1,2))  

还有一种方法就是通过在变量外部加上“__block”说明符,其实加了__Block之后,这个变量就变成了一个结构体指针变量,这个原理和静态变量一样,由传值方式改为指针传递,所以就可以更改变量了。
如下所示


__block int c = 0;  
  
int (^addFun)(int,int) = ^int(int a,int b){  
    c = 1;  
    return a + b + c;  
};  
NSLog(@"addValue = %d",addFun(1,2));  

4.2、如何避免Block的循环引用

** 待补充**

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

推荐阅读更多精彩内容

  • 《Objective-C高级编程》这本书就讲了三个东西:自动引用计数、block、GCD,偏向于从原理上对这些内容...
    WeiHing阅读 9,804评论 10 69
  • 前言 Blocks是C语言的扩充功能,而Apple 在OS X Snow Leopard 和 iOS 4中引入了这...
    小人不才阅读 3,759评论 0 23
  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,135评论 30 470
  • 在介绍Block之前通过一个简单的应用场景认识下Block 场景描述如下:TableView上面有多个Custom...
    黑_白_灰阅读 1,385评论 4 29
  • 摘要 Blocks是C语言的扩充功能, iOS 4中引入了这个新功能“Blocks”,那么block到底是什么东西...
    CholMay阅读 1,160评论 2 10