代码块(block)

1. 代码块 (block)

block 类似于c语言的函数指针 但是比函数指针功能更强,是多种高级语言提供的"闭包"

2. 代码块的定义

代码块的定义和函数指针相似
//返回类型为void的block 定义一个block 返回类型不加括号
void(^myblock)(NSString*str);
 //给block赋值
 myBlock = ^(NSString *str) {
            NSLog(@"%@", str);
        };
//调用block
        myBlock(@"测试!");          

2.带返回类型的block

//定义了一个block, 注意:返回类型不能加括号
//定义block时,指明返回类型
//给block赋值
//注意^前面没有返回类型,通过block内部的return判定返回类型          
  myBlock = ^(NSString *str) {
            str = [NSString stringWithFormat:@"收到:%@", str];         
   return str;
        };       

//调用block
NSString *value = myBlock(@"测试!");       
NSLog(@"%@", value);

3 不带参参数的block 在给block 赋值的时候 如果不带参数,则等号右边是块定义可以省略参数列表 但是定义block变量时 即使没有参数也需要有()

void*(^myblock)();//没有参数的block
myblock= ^{
    //执行的代码
}
myblcok();//调用block

4 定义的同时 初始化blcok

NSString *(^myBlock)(NSString*str)= ^(NSString*str){
    str = [NSString stringWithFormat:@"%@",str];
    return str;
}
//调用block
NSString *Value = myblock(@"测试数据");
NSlog(@"%@",Value);

3. 捕获

1 block内使用block定义体之外的变量

Nsstring* name = @"mybock";
NSString*(^myblock)(NSString*str) = ^(NSString*str){
    str = [NSString stringWithFormat:@"%@%@",str,name];
    return str;
};
//调用block
NSlog(@"%@",myblcok(@"测试数据"));

1 代码块内可以”捕获”代码块以外的变量
全局变量 block 内使用全局变量时 该 全局变量被捕获为变量
被捕获的全局变量变化时 block内的相应变量也会发生相应的变化
2 使用局部变量 block内使用局部变量 该局部变量捕获为常量
block 内的相变量不会发生变化
3 使用静态变量时 被捕获为 变量
4 使用指向oc对象的指针 如果该指针变量也被捕获为常量 但是指针所指向的对象是可以变化的
5 block 内捕获oc对象时 , 是强引用 可能产生循环引用 导致内存泄漏

@interface Car : NSObject

@property (nonatomic, copy) void (^myBlock) (void);

@property (nonatomic) float length;
@property (nonatomic) float width;
@property (nonatomic) float height;

- (instancetype)initWithLength:(float)length andWidth:(float)width andHeight:(float)height;
@end
这里写代码#import "Car.h"

@implementation Car

- (instancetype)initWithLength:(float)length andWidth:(float)width andHeight:(float)height
{
    self = [super init];
    if (self) {
        _length = length;
        _width = width;
        _height = height;
    }
    return self;
}

- (NSString*) description
{
    return [NSString stringWithFormat:@"%.2f,%.2f,%2.f", _length, _width, _height];
}

- (void)dealloc
{
    NSLog(@"销毁汽车, %p", self);
}

@end
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Car *car = [Car new];
        car.length = 5.4;

        car.myBlock = ^{
            NSLog(@"%@", car);  //导致强“循环引用”
        };
        car.myBlock();

    }
    return 0;
}

解决方案 :

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Car *car = [Car new];
        car.length = 5.4;
        __weak Car *car2 = car;
        car.myBlock = ^{
            NSLog(@"%@", car2);
        };
            car.myBlock();

    }
    return 0;
}    

注意:block的参数,和普通函数的参数一样,每次执行时,根据参数的当前实际值处理。

nt a = 10;
int b = 20;

void (^testBlock)(int, int) = ^(int a, int b){
    NSLog(@"%d", a+b);
};
testBlock(a, b);  //30

a++;
testBlock(a, b); //31
  1. 使用__block
    block内捕获局部变量时,被识别为“常量”,导致:
    1)被捕获的局部变量的值变化时,block内对应的值不能改变。
    2)在block内不能直接改变被捕获的变量的值。
    如果强行改变,将无法通过编译。

解决方案:
使用__block, 即被捕获的局部变量使用__block特性进行修饰。

__block NSString *name = @"Lufy";
        NSString* (^myBlock)(NSString *str) = ^(NSString *str) {
            str = [NSString stringWithFormat:@"%@%@", str, name];
            return str;
        };

        //调用block
        NSLog(@"%@", myBlock(@"测试"));

        name = @"Shanji";
        NSLog(@"%@", myBlock(@"测试"));
  1. block作为函数的参数
    用法类似于c语言中,使用函数指针实现回调
NSArray *array1 = @[@"Hello", @"world", @"good", @"morning"];
NSArray *array2 = [array1 sortedArrayUsingComparator:^(NSString *str1, NSString *str2) {
            return [str1 compare:str2];
}];

或者使用block变量

NSArray *array1 = @[@"Hello", @"world", @"good", @"morning"];
NSComparisonResult (^compare)(NSString*, NSString*) = ^(NSString *str1, NSString *str2) {
    return [str1 compare:str2];
};
NSArray *array2 = [array1 sortedArrayUsingComparator:compare];
  1. 使用typedef定义block类型
    使用typedef可以使block变量的定义简化
NSString *name = @"Lufy";

        typedef void (^myBlock_t)(NSString*);
        myBlock_t myBlock = ^(NSString *act){
            NSLog(@"%@, %@!", act, name);
        };
posted @ 2016-03-24 22:13  夜色下的港湾  Views(345)  Comments(0Edit  收藏  举报