zoukankan      html  css  js  c++  java
  • iOS

    Block 的使用有两种:
    1.独立Block
    2.内联Block
     
     
    《一》独立Block 使用方式
     
    一、定义一个Block Object,并调用。
     
    1.定义
     
    // 定义一个Block Object,返回值:NSString;别名:intToString;参数:NSUInteger。
    
    NSString* (^intToString)(NSUInteger) = ^(NSUInteger paramInteger){
    
        NSString *result = [NSString stringWithFormat:@"%lu",(unsignedlong)paramInteger];
    
        return result;
    
    };
     
    2.调用
     
    // 调用我们定义的Block Ojbect
    
    NSString *string = intToString(10);
    
    NSLog(@"string = %@", string);
    二、将Block Object 当作参数,在方法之间传递,调用。
     
    有时候,我们希望将定义的Block Object作为函数的参数使用,就像其他的数据类型一样。
     
    1.为Block Object 定义签名
     
    typedef NSString* (^IntToStringConverter)(NSUInteger paramInteger);
     
    这就告诉,编译器,我们定义了一个签名(别名)为IntToStringConverter 的Block Object。这个Block返回值为:NSString;参数为:NSUInteger。
     
    2.定义使用Block为参数的函数
     
    - (NSString *)convertIntToString:(NSUInteger)paramInteger usingBlockObject:(IntToStringConverter)paramBlockObject{
    
        
    
        return paramBlockObject(paramInteger);
    
    }
     
    这一步,很简单,我们将前面定义的Block作为了一种类型。这种类型为:IntToStringConverter
     
    3.调用使用Block为参数的方法
     
     NSString *result = [self convertIntToString:123 usingBlockObject:intToString];
    
        NSLog(@"result = %@", result);
    调用时,123,和intToString可理解为实参。
     
    《二》内联Block 使用方式
     
    在此之前,让我们梳理一下需要的代码:
     
    1.定义
    typedef NSString* (^IntToStringConverter)(NSUInteger paramInteger);
     
    2.用Block作为参数的函数
    - (NSString *)convertIntToString:(NSUInteger)paramInteger usingBlockObject:(IntToStringConverter)paramBlockObject{
    
        
    
        return paramBlockObject(paramInteger);
    
    }
     
    3.内联调用
    - (void) doTheConversion{
    
        IntToStringConverter inlineConverter = ^(NSUInteger paramInteger){
    
            NSString *result = [NSString stringWithFormat:@"%lu", (unsignedlong)paramInteger];
    
            return result;
    
        };
    
        
    
        NSString *result = [self convertIntToString:123usingBlockObject:inlineConverter];
    
        NSLog(@"result = %@", result);
    
        
    
    }
     
    调用的时候,只需要这样:
    [self doTheConversion];

     

    什么是内联Block?

    我的理解是,写在方法内部的,编译器在编译阶段无法知道要调用的具体Block内容。

    就像上边的例子:

    独立Block:在编译阶段,已经就定义好了Block方法:

     

    // 定义一个Block Object,返回值:NSString;别名:intToString;参数:NSUInteger。
    
    NSString* (^intToString)(NSUInteger) = ^(NSUInteger paramInteger){
    
        NSString *result = [NSString stringWithFormat:@"%lu",(unsigned long)paramInteger];
    
        return result;
    
    };

    内联Block:在编译阶段,编译器并不知道所关联的Block是什么。

    因为它是在调用doTheConversion方法时,临时分配的(inlineConverter)。红色块。

     

     

    - (void) doTheConversion{
    
        IntToStringConverter inlineConverter = ^(NSUInteger paramInteger){
    
            NSString *result = [NSString stringWithFormat:@"%lu", (unsignedlong)paramInteger];
    
            return result;
    
        };
    
        
    
        NSString *result = [self convertIntToString:123 usingBlockObject:inlineConverter];
    
        NSLog(@"result = %@", result);
    
        
    
    }

     

    同理,就相当于:

     

    - (void) doTheConversion{
    
       
    
         NSString *result =[self convertIntToString:123
    
                                   usingBlockObject:^(NSUInteger paramInteger) {
    
                                       NSString *result = [NSStringstringWithFormat:@"%lu",(unsigned long)paramInteger];
    
                                       return result;
    
                                   }];
    
        
    
        NSLog(@"result = %@", result);
    
     
    
    }

     

    是啊,很多iOS中的方法,用的都是这种方式!对用的就是内联Block!!!

    原来如此啊!

     

    先mark到这里吧!

     

    下一步,我们来了解一下,关于Block变量的一些东西!

     

    Block 的变量

     

    1.独立Block 变量的操作。

     

    定义Block:
    
     
    
    void (^independentBlockObject)(void) = ^(void){
    
        NSInteger localInteger = 10;
    
        NSLog(@"local integer = %ld", (long)localInteger);
    
        localInteger = 20;
    
        NSLog(@"local integer = %ld", (long)localInteger);
    
     
    
    };

     

    调用:

     

    independentBlockObject();

     

    输出:

     

    2016-03-26 20:13:50.144 DemoVideo[20505:707] local integer = 10
    
    2016-03-26 20:13:50.147 DemoVideo[20505:707] local integer = 20
    
     

     

    2.内联Block 变量的操作。

     

    我们知道Object-C中已经有很多用Block作为参数的函数。该Block参数,作为内联Block调用。

    于是,就用一个数组比较的方法:

     

    定义:
    
     
    
     
    
    - (void) simpleMethod{
    
        NSMutableArray *array = [[NSMutableArray alloc]initWithObjects:@"100",@"200",@"150", nil];
    
        
    
        NSArray *sortedArray = [array sortedArrayUsingComparator: ^(id obj1, id obj2) {
    
            
    
            if ([obj1 integerValue] > [obj2 integerValue]) {
    
                return (NSComparisonResult)NSOrderedDescending;
    
            }
    
            
    
            if ([obj1 integerValue] < [obj2 integerValue]) {
    
                return (NSComparisonResult)NSOrderedAscending;
    
            }
    
            return (NSComparisonResult)NSOrderedSame;
    
        }];
    
        
    
    }

     

    调用:

     

     

    [self simpleMethod];

     

    输出:

     

     

    Printing description of sortedArray:
    
    <__NSArrayI 0x1f56d430>(
    
    100,
    
    150,
    
    200
    
    )
    
    Printing description of array:
    
    <__NSArrayM 0x1f585ed0>(
    
    100,
    
    200,
    
    150
    
    )

     

    我们不用关心,sortedArrayUsingComparator方法的内部实现是什么,但是,它在运行中,调用了内部变量:obj1和obj2

     

    可见:独立Block可以在内部定义变量,访问变量,修改变量!

     

    Block可以读写自己内部的变量,那么对于外部变量,有如何呢 ?

     

    不着急,我们先来归纳一下用于测试的相关代码:

    定义Block签名
    
     
    
    typedef NSString* (^UserMyBlockFun)(NSUInteger paramInteger);
    
    定义Block为参数的函数
    
     
    
    - (NSString *)convertIntToString:(NSUInteger)paramInteger usingBlockObject:(UserMyBlockFun)paramBlockObject{
    
        
    
        return paramBlockObject(paramInteger);
    
    }
    
     
    
    定义调用函数:
    
     
    
     
    
    - (void) doTheConversion{
    
        
    
        __block int outsideVariable=6;
    
        
    
        NSString *result =[self convertIntToString:123
    
                                  usingBlockObject:^(NSUInteger paramInteger) {
    
                                      // 访问self
    
                                      NSLog(@"self = %@", self);
    
                                      // 访问self的实体变量
    
                                      NSLog(@"self = %@", self.strName);
    
                                      
    
                                      int insideVariable=10;
    
                                      insideVariable+=5;
    
                                      
    
                                      // 输出内部变量,没问题,对内部变量可读写
    
                                      NSLog(@"insideVariable:%d",insideVariable);
    
                                      // 输出外部变量,可以读取外部变量,但是不能修改,否则将报出一个错误。
    
                                      // Variable is not assignable(missing __block type specifier)
    
                                      NSLog(@"outSideVariable:%d",outsideVariable);
    
                                      
    
    //                                  outsideVariable+=3;
    
                                      
    
                                      NSLog(@"outSideVariable:%d",outsideVariable);
    
                                      
    
                                      NSString *result = [NSString stringWithFormat:@"%lu",(unsigned long)paramInteger];
    
                                      return result;
    
                                  }];
    
        
    
        NSLog(@"result = %@", result);
    
        
    
    }
     

    可见,对于外部普通变量,Block只有读取的权限。

    但是,从一个错误:Variable is not assignable(missing __block type specifier)中,也许我们可以知道,

     

    如果,要对外部变量具有写权限,那么就要在变量前,加上“__block”

     

     __block int outsideVariable=6;

    这样,就可以读写outsideVariable变量了。

     

    内联Block可以直接访问self;但是,独立Block不能直接访问self,替代方式为,将self作为参数,传递给Block。

     

    如:

    // 独立Block
    
    void (^correctBlockObject)(id) = ^(id self){
    
        // 将self作为参数传递
    
        NSLog(@"self = %@", self);
    
        // 访问self变量
    
        NSLog(@"self = %@", [self strName]);
    
        
    
    };
    
     
    
    - (void) callCorrectBlockObject{
    
        correctBlockObject(self);
    
    }

    有一点非常重要:

     

    内联Block,调用的外部变量,使用的是复制方式。

     

    运行一下,查看输出就知道了:

     

    - (void) scopeTest{
    
        NSUInteger integerValue = 10;
    
        // 定义内联Block
    
        BlockWithNoParams myBlock = ^{
    
            NSLog(@"Integer value inside the block = %lu", (unsignedlong)integerValue);
    
        };
    
        
    
        integerValue = 20;
    
        // 调用Block
    
        myBlock();
    
        NSLog(@"Integer value outside the block = %lu",(unsigned long)integerValue);
    
     
    
    }

    如果要使用引用方式,那么就要在变量前加上“ __block”

     

    调用 Block 

     

    关于内联Block,因为其就是写在方法内的,所以,调用起来相对方便。就像iOS中的API,有很多方法,使用了内联Block方式。

     

    关于独立Block,主要使用C语言的函数调用方式。

     

    用例子来说明吧。

     

    1.调用Block

     

    // 定义Block
    
    void (^simpleBlock)(NSString *) = ^(NSString *theParam){
    
        NSLog(@"the string=%@",theParam);
    
        
    
    };
    
     
    
    // 调用Block
    
    - (void) callSimpleBlock{
    
        simpleBlock(@"O'Reilly");
    
    }

     

    2.嵌套调用

     

    // 定义内层Block
    
    NSString *(^trimString)(NSString *) = ^(NSString *inputString){
    
        NSString *result = [inputString stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]];
    
        return result;
    
    };
    
    // 定义外层Block
    
    NSString *(^trimWithOtherBlock)(NSString *) = ^(NSString *inputString){
    
        return trimString(inputString);
    
    };
    
     
    
    // 调用方法
    
    - (void) callTrimBlock{
    
        NSString *trimmedString = trimWithOtherBlock(@" O'Reilly ");
    
        NSLog(@"Trimmed string = %@", trimmedString);
    
    }
  • 相关阅读:
    配置日志
    部署项目到jetty
    部署web应用程序到tomcat
    spring boot 整合mybatis
    创建spring boot 项目
    发送http请求
    pom.xml文件中dependency标签的scope子标签
    Ubuntu apparmor何方神圣
    Ubuntu Nginx下配置网站ssl实现https访问
    打造私有的DNS 服务
  • 原文地址:https://www.cnblogs.com/gongyuhonglou/p/6999545.html
Copyright © 2011-2022 走看看