1.block 用到的局部变量是 只读的,将关键字__block 定义局部变量 则变为可读写。
2.如果局部变量类型是 基本数据类型,比如NSinteger,那么block使用局部变量其实是其拷贝,类似于函数参数传值方式,所以在定义block之后修改局部变量对block代码块的内容没有影响。
NSInteger outNum11 = 10;
NSInteger (^blockOne11)(NSInteger) = ^(NSInteger a){NSLog(@">>>%p %d",&outNum11,outNum11); return outNum11+a;};
outNum11 =5;
NSLog(@">>>&outnum11=%p %d",&outNum11,outNum11);
NSLog(@">>>%d ",blockOne11(3));
输出结果,是13而不是8,从outNum11的地址指针也可以看出两者已经不同。
2012-09-02 11:33:51.606 TestBlockExample[984:f803] >>>&outnum11=0xbfffdcf4 5
2012-09-02 11:33:51.608 TestBlockExample[984:f803] >>>0xbfffdcec 10
2012-09-02 11:33:51.610 TestBlockExample[984:f803] >>>13
3.如果局部变量类型是 NSobject类型,那么block使用局部变量,仍按函数参数传值方式,只是此时局部变量类型为指针,其值为指针所指对象地址,所以指针按值拷贝后仍指向相同的对象地址。
NSMutableArray* outArray = [NSMutableArray arrayWithObjects:@"one",@"two",@"three", nil];
NSMutableArray* (^blockOne)(NSMutableArray*) = ^(NSMutableArray* array){NSLog(@"\n>>>block %p %p %@",&outArray,outArray,outArray);[array removeLastObject]; return array;};
[outArray removeObjectAtIndex:0];
NSLog(@"\n>>>main %p %p %@",&outArray,outArray,outArray);
NSLog(@"\n>>>result%@ %p %p %@",blockOne(outArray),&outArray,outArray,outArray);
输出结果
2012-09-02 11:40:13.213 TestBlockExample[1072:f803]
>>>main 0xbfffdcd4 0x6a2d4f0 (
two,
three
)
2012-09-02 11:40:13.213 TestBlockExample[1072:f803]
>>>block 0xbfffdccc 0x6a2d4f0 (
two,
three
)
2012-09-02 11:40:13.214 TestBlockExample[1072:f803]
>>>result(
two
) 0xbfffdcd4 0x6a2d4f0 (
two
)
4.若局部变量加上__block,则block内局部变量变为可读写,其实这时是类似于将原来使用的局部变量 按传值方式改为 传地址方式。
__block NSInteger outNum11 = 10;
NSInteger (^blockOne11)(NSInteger) = ^(NSInteger a){NSLog(@">>>block %p %d",&outNum11,outNum11); return outNum11+a;};
outNum11 =5;
NSLog(@">>>main =%p %d",&outNum11,outNum11);
NSLog(@">>>%d ",blockOne11(3));
输出结果,可以看到此时block中的局部变量地址没变
2012-09-02 11:49:08.557 TestBlockExample[1108:f803] >>>&outnum11=0xbfffdcf8 5
2012-09-02 11:49:08.559 TestBlockExample[1108:f803] >>>0xbfffdcf8 5
2012-09-02 11:49:08.560 TestBlockExample[1108:f803] >>>8
局部变量为NSobject对象时
__block NSMutableArray* outArray = [NSMutableArray arrayWithObjects:@"one",@"two",@"three", nil];
NSMutableArray* (^blockOne)(NSMutableArray*) = ^(NSMutableArray* array){NSLog(@"\n>>>block %p %p %@",&outArray,outArray,outArray);[array removeLastObject]; return array;};
[outArray removeObjectAtIndex:0];
NSLog(@"\n>>>main %p %p %@",&outArray,outArray,outArray);
NSLog(@"\n>>>result%@ %p %p %@",blockOne(outArray),&outArray,outArray,outArray);
输出结果,
2012-09-02 11:55:43.666 TestBlockExample[1197:f803]
>>>main 0xbfffdcf0 0x68b69e0 (
two,
three
)
2012-09-02 11:55:43.666 TestBlockExample[1197:f803]
>>>block 0xbfffdcf0 0x68b69e0 (
two,
three
)
2012-09-02 11:55:43.667 TestBlockExample[1197:f803]
>>>result(
two
) 0xbfffdcf0 0x68b69e0 (
two
)
5.如果局部变量为static,则直接可以读写的,原因一样,因为是静态的,所以只有一份
static NSInteger outNum11 = 10;
NSInteger (^blockOne11)(NSInteger) = ^(NSInteger a){NSLog(@">>>block %p %d",&outNum11,outNum11); outNum11=7; return outNum11+a;};
outNum11 =5;
NSLog(@">>>main =%p %d",&outNum11,outNum11);
NSLog(@">>>%d ",blockOne11(3));
输出结果:
2012-09-02 11:55:43.663 TestBlockExample[1197:f803] >>>main =0x4730 5
2012-09-02 11:55:43.665 TestBlockExample[1197:f803] >>>block 0x4730 5
2012-09-02 11:55:43.666 TestBlockExample[1197:f803] >>>10
6.定义block 指针类似与 函数指针,可以作为 方法的参数
NSInteger (^blockOne11)(NSInteger) = ^(NSInteger a){NSLog(@">>>block %p %d",&outNum11,outNum11); outNum11=7; return outNum11+a;};
- (void)testBlock:(NSString*(^)(NSString*input))inputBlock
{
NSLog(@">>>result=%@", inputBlock(@"kkk"));
}
7.block 也是继承与NSobject,block一般分配与stack,所以退出对应程序块时会自动释放,所以通过方法返回block时需要 对block指针做copy 在返回。
block与NSobject对象不同是,不能向block对象发送消息。
如果对block对象copy 则会自动对局部变量做retain(如果是NSObject),或拷贝到heap中(非NSobject对象)。另外,当局部变量使用了__block关键字,则不retain
8.如果block存取 类实例成员,不管通过存取器或直接访问成员,都会retain self 和该实例变量。