zoukankan      html  css  js  c++  java
  • 代码块(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);
            };
  • 相关阅读:
    国产CPU研究单位及现状
    大型网站用什么技术比较好,JSP,PHP,ASP.NET
    韩国企业百强排行榜!
    中国操作系统
    Visual C++2010开发权威指南 中文高清PDF
    printf以及各种变种
    SPDY以及HTTP2.0
    数字证书认证这点事, SSL/TLS,OpenSSL
    利用Fiddler,解密wireshark抓的HTTPS包
    C跟C++
  • 原文地址:https://www.cnblogs.com/Sico2Sico/p/5384282.html
Copyright © 2011-2022 走看看