zoukankan      html  css  js  c++  java
  • GCD2 :在Block Object中访问变量

    问题:

    你想要理解在 Objective-C 方法和在 Block Objects 中访问变量的区别 

     方案:

    这儿简单总结一下关于 Block Objects 变量你需要知道的内容:
    1.局部变量在 Block Objects 和 Objective-C 方法中的工作原理非常相似。
     
    2.对于内联Block Objects,局部变量不仅包含Block内部定义的变量,并且包含在Block Objects 执行方法中定义的变量。(随后会有举例)

    3.在 Objective-C 类中运行的独立 Block Objects 中你不能直接使用 self;如果你需要访问 self, 就必须把 Object 作为参数传递到

    BlockObject,我们很快会看到举例。

    4.只有当self出现在创建Block Object的词法范围内,你可以在内联Block Object内直接使用 self。

    5.对于内联 Block Objects,那些在 BlockObject 执行过程中定义的局部变量是可读写的,换句话说,对于 Block Objects 自身的局部变量来说,可以对其读写。

    6.对于内联 Block Objects,实现 Object 的 Objective-C 方法的局部变量只能从中读取, 不能写入。不过还有一个例外,如果定义它们通过 __block 存储类型定义的话,Block Object 可以写入此类的变量。对此我们也会有举例。

    7.假设你有一个类 NSObject 的 Object,并且在这个 Object 的执行中你使用了一个Block Object与GCD相连,那么在这个Block Object内部,你会有一个存储来读取那个支持你的 Block 执行的 NSObject 内部的声明属性。

    8.只有当你使用声明属性的 setter and getter 方法你才能获取独立 Block Objects 内部的NSObject 的这些属性;在一个独立 Block Object 使用“.”符号你无法获取一个 Object 的声明属性。 

    讨论:

    1.

    如何在两个 Block Objects 的执行过程中使用变量;一个是内联 Block Object,另一个是独立 Block Objects :
    - (void)simpleMethod{
        NSUInteger outsideVariable = 10;
        NSMutableArray *array = [[NSMutableArray alloc]initWithObjects:@"obj1",@"obj2", nil];
        [array sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
            NSUInteger insideVariable = 20;
            NSLog(@"Outside variable = %lu",(unsigned long)outsideVariable);
            NSLog(@"Inside variable = %lu", (unsigned long)insideVariable);
            /* Return value for the block object */
            return NSOrderedSame;
        }];
    }
    Block Object 可以读写它自己的 insideVariable 局部变量。然而,对于默认的 outsideVariable 变量,Block Object 只能读不能写。 
     
    为了允许 Block Object 写入 outsideVariable,我们必须给 outside Variable 增加一个__block 存储类的前缀: 
    - (void)simpleMethod{
        __block NSUInteger outsideVariable = 10;
        NSMutableArray *array = [[NSMutableArray alloc]initWithObjects:@"obj1",@"obj2", nil];
        [array sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
            outsideVariable = 30;
            NSUInteger insideVariable = 20;
            NSLog(@"Outside variable = %lu",(unsigned long)outsideVariable);
            NSLog(@"Inside variable = %lu", (unsigned long)insideVariable);
            /* Return value for the block object */
            return NSOrderedSame;
        }];
    }

    2.

     在内联 block 中访问 self 是可行的,这跟在内联 block 中创建的对象一样。例如,在这个例子中,Block Object 将会访问 self,因为 simpleMethod 是一个 Objective-C 类的实例: 

    - (void)simpleMethod2{
        NSMutableArray *array = [[NSMutableArray alloc]initWithObjects:@"obj1",@"obj2", nil];
        [array sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
            NSLog(@"self = %@",self);
            return NSOrderedSame;
        }];
    }
     
    独立 Block Objects不能直接访问self...
    void (^incorrectBlockObject)(void) = ^{
    NSLog(@"self = %@", self); /* self is undefined here */ 
    };
    编译时出现错误....

    如果你想从独立 Block Objects 中访问 self,只要简单的将 self 以参数的方式传递到 block 中即可: 

    void (^incorrectBlockObject)(id) = ^(id self){
        NSLog(@"self = %@",self);
    };

    3.Block与已声明的属性

    在内联Block Objects中,可以直接使用“.”符号读写 self 已声明属性。

    [array sortUsingComparator:^NSComparisonResult(id obj1, id obj2) { NSLog(@"self = %@", self);
    self.stringProperty = @"Block Objects";
    NSLog(@"String property = %@", self.stringProperty);
    /* Return value for the block object */
    return NSOrderedSame;
    }];

    而在独立Block Object 内部,你不能使用“.”符号读写一个已声明属性.

     此时可以使用这个合成属性的 getter and setter 方法来代替“.”符号: 

    incorrectBlockObject(self);
    void (^incorrectBlockObject)(id) = ^(id self){
        NSLog(@"self = %@",self);
        //self.stringProperty = @"Block";  独立block不能直接用点语法读写属性
        [self setStringProperty:@"Block Objects"];
        NSLog(@"self.stringProperty = %@",[self stringProperty]);
    };

    4.

    内联 Block Objects 在其词法区域会对变量的值进行拷贝。 
    如果不明白这一点,不要担心,我们看个例子: 
    typedef void(^BlockWithNoParams)(void);
    - (void)scopeTest{
        NSUInteger integerValue = 10;
        /********** Definition(定义) of internal block object ***********/
        BlockWithNoParams myBlock = ^{
            NSLog(@"Integer value inside the block = %lu",(unsigned long)integerValue);
        };
        /*************** End definition of internal block object ************/
        integerValue = 20;
        /* Call the block here after changing the value of the integerValue variable */
        
        NSLog(@"Integer value outside the block = %lu", (unsigned long)integerValue);
        myBlock();
    }

    控制台输出为:

    Integer value outside the block = 20

    Integer value inside the block = 10

     为什么输出结果是这样呢: 我们在实现Block Object时对integerValue进行了拷贝

    如果要改变这个现象呢?

    方法是,我们要在需要修改的变量前加上__block前缀:

    - (void)scopeTest{
        __block NSUInteger integerValue = 10;
        /********** Definition(定义) of internal block object ***********/
        BlockWithNoParams myBlock = ^{
            NSLog(@"Integer value inside the block = %lu",(unsigned long)integerValue);
        };
        /*************** End definition of internal block object ************/
        integerValue = 20;
        /* Call the block here after changing the value of the integerValue variable */
        
        NSLog(@"Integer value outside the block = %lu", (unsigned long)integerValue);
        myBlock();
    }

    输出为

    Integer value outside the block = 20

    Integer value inside the block = 20

     

  • 相关阅读:
    【转】 robotframework(rf)中对时间操作的datetime库常用关键字
    在RobotFramework--RIDE中把日期转化为整型进行运算
    Oracle中date转为timstam可以函数to_timestamp的方式来转化
    Java项目缺少.project文件
    数据库时间戳转换日期(MYSQL数据库)
    spring+struts+mybatis中关于报错org.hibernate.exception.GenericJDBCException: Connection is read-only. Queries leading to data modification are not allowed 的产生原因及解决方案
    新加字段问题(增加联合主键)
    集合问题
    数组面试题
    集合的问题
  • 原文地址:https://www.cnblogs.com/safiri/p/4058803.html
Copyright © 2011-2022 走看看