6.2 Accessing Variables in Block Objects

来源:互联网 发布:java程序员前景 编辑:程序博客网 时间:2024/06/01 09:23

在block对象中访问变量

这里有几点,你必须知道:
1,block对象内的局部变量的使用方法与OC方法中使用局部变量一样。
2,对于内联block 对象,局部变量不仅包括在block对象内定义的变量,还包括外层方法中定义的变量。
3,OC类中实现的独立的block对象内不能使用self。如果你需要访问类对象,你应该把它作为参数传过去。
4,只有在内联block对象被创建的当前逻辑范围内self可以被引用时,block对象才可以引用self。
5,对于内联block对象内定义的变量,block对象具有读写权限。
6,对于内联block对象,其外层方法定义的变量,内联函数只有读权限,没有写权限。除非他们被定义成 __block storage类型。
7,在NSObject对象的实现内使用GCD共同实现的Block对象(a block object in conjunction with GCD),在这个对象内可以对NSObject声明的属性进行读写。
8,在独立的block对象中,你也可以访问NSObject声明的属性,不过你要使用其setter和getter方法,而不能使用点语法。

先看下两个block对象,一个是内联的,一个是独立的。
独立的:
void (^independentBlockObject)(void) = ^(void){
NSInteger localInteger = 10;
NSLog(@"local integer = %ld", (long)localInteger);
localInteger = 20;
NSLog(@"local integer = %ld", (long)localInteger);
};

内联的:
- (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对象内,我们无法修改outsideVariable的值,如果想修改必须先给声明加上前缀 __block,修改结果如下:
- (void) simpleMethod{
__block NSUInteger outsideVariable = 10;
NSMutableArray *array = [[NSMutableArray alloc]
initWithObjects:@"obj1",
@"obj2", nil];
[array sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
NSUInteger insideVariable = 20;
outsideVariable = 30;
NSLog(@"Outside variable = %lu", (unsigned long)outsideVariable);
NSLog(@"Inside variable = %lu", (unsigned long)insideVariable);
/* Return value for the block object */
return NSOrderedSame;
}];
}

在内联block对象内也可以访问self,只要其在逻辑范围内是可访问的:
- (void) simpleMethod{
NSMutableArray *array = [[NSMutableArray alloc]
initWithObjects:@"obj1",
@"obj2", nil];
[array sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
NSLog(@"self = %@", self);
/* Return value for the block object */
return NSOrderedSame;
}];
}

但是对于独立的block对象,就不能这么访问了,如下是错的:
void (^incorrectBlockObject)(void) = ^{
NSLog(@"self = %@", self); /* self is undefined here */
};
想要访问self,你应该把它作为参数传过去:
void (^correctBlockObject)(id) = ^(id self){
NSLog(@"self = %@", self);
};
- (void) callCorrectBlockObject{
correctBlockObject(self);
}
注:这里的形参不一定要用self,但是当你想把它拷贝到另一个函数中,作为内联block时,你就不需要再去改这个形参的名称了,是不是?


在内联block对象中,你可以使用点语法读写self的属性。假设有这么个类:

#import <UIKit/UIKit.h>
@interface GCDAppDelegate : NSObject <UIApplicationDelegate>
@property (nonatomic, strong) NSString *stringProperty;
@end

我们可以在内联block对象中这么访问属性:
#import "GCDAppDelegate.h"
@implementation GCDAppDelegate
- (void) simpleMethod{
NSMutableArray *array = [[NSMutableArray alloc]
initWithObjects:@"obj1",
@"obj2", nil];
[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;
}];
}
@end

但是在独立的block对象中,我们不能使用点语法来读写属性,如下会编译错误:
void (^correctBlockObject)(id) = ^(id self){
NSLog(@"self = %@", self);
/* Should use setter method instead of this */
self.stringProperty = @"Block Objects"; /* Compile-time Error */
/* Should use getter method instead of this */
NSLog(@"self.stringProperty = %@",
self.stringProperty); /* Compile-time Error */
};
应该这么写:
void (^correctBlockObject)(id) = ^(id self){
NSLog(@"self = %@", self);
/* This will work fine */
[self setStringProperty:@"Block Objects"];
/* This will work fine as well */
NSLog(@"self.stringProperty = %@",
[self stringProperty]);
};

内联block对象有一个重要的规则是,它拷贝了逻辑范围内的变量的值,上例子:
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 */
myBlock();
NSLog(@"Integer value outside the block = %lu",
(unsigned long)integerValue);
}
Block实现的时候integerValue的值是10,调用的时候其值是20,那么block内部答应出来的结果是多少呢?这个函数的执行结果:
Integer value inside the block = 10
Integer value outside the block = 20
怎么回事,为什么是10,而不是20?因为block在实现的时候给自己保存了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 */
myBlock();
NSLog(@"Integer value outside the block = %lu",
(unsigned long)integerValue);
}
这时打印的结果就是:
Integer value inside the block = 20
Integer value outside the block = 20

OK,block对象使用变量的相关法则已经介绍完了,啥时候要是忘了,可得记得回来看看哦。

 

 

 


 

0 0
原创粉丝点击