Block

Block简介

  • Block 是 iOS 4.0 和 Mac OSX 10.6 引入的一个新特性。
  • 没有 Block 时, 一般会用代理或者 NSNotificationCenter回调一个方法,在一个地方开启了一个任务, 然后在另外一个地方处理它的结果。Block能将和一个任务相关的所有代码都放在一个地方。
  • 在其它语言中 Block 又叫做闭包, 因为他们包含了定义时的状态。 Block 会为所有和它在同一作用范围内的局部变量创建一个常量拷贝。
  • Block 是一个标准 Objective-C 对象, 可以作为参数传递, 作为方法或函数的返回值, 赋值给变量。

Block 的声明格式

return_type (^block_name)(param_type, param_type, ...)

^符号表示定义的是一个 Block。
代码示例:

 int (^add)(int,int)

Block 的定义格式:

 ^return_type(param_type param_name, ...) { ... return return_type; }

定义 Block 时, 返回值类型可选,可以继承它里面代码的返回值类型
示例:

 ^(int number1, int number2){ return number1+number2; }

声明并定义Block

示例:

 int (^add)(int,int) = ^(int number1, int number2)
 {
 return number1+number2;
 };

循环引用(retain-cycle)问题

如果这个block没有使用当前实例的任何成员,那么当前实例不会被增加引用计数。
如果objc类实例方法中的block如果被复制至heap,那么当前实例会被增加引用计数,当这个block被释放时,此实例会被减少引用计数。但若block和当前实例互相直接或间接retain,则会出现循环引用问题。

解决方法:不直接使用self而先将self赋值给一个__block临时变量,然后再使用这个临时变量。示例:

__block DetailViewController* tempSelf = self;
//或者 __block typeof(self) tempSelf = self;
 [replyViewController_ setFinishBlock:^{
 [tempSelf method];
 tempSelf->member=0;
 }];

__block关键字的作用是让block取消对tempSelf的强参照,以避免循环参照。在ARC下,要使用__weak不是 __block来避免block循环引用;

若出现typeof(self) Expected ‘;’ at end of declaration编译错误,需要修改设置 Apple LLVM 5.1 Language C Language Dialect 值为 GNU99 [-std=gnu99]

You do not have to jump through this hoop for every block you make because most blocks have a very short lifespan. Just be aware that if you have a block that has the same lifetime as its owning object and you are freeing the block at -dealloc time, you can get a retain cycle.

http://www.informit.com/articles/article.aspx?p=1749597&seqNum=10

外部变量问题

若非即执行的block中外部变量是可变的,则注意在每次调用时要重新生成一个block。

 BOOL isFriends=[INSTANCE.contextData isFriendWithUser:userInfo];
 if(!replyViewController_)
 {
 replyViewController_=[[ReplyChatViewController alloc] initWithPlaceholder:@"打个招呼吧"];
 }
 //每次要重新设置block,因为其使用的外部变量值每次不同。
 __block MapViewController* tempself=self;
 [replyViewController_ setFinishBlock:^{
 if(!isFriends && INSTANCE.serverSetting.costMakeFriends>0)
 {
 [tempself performSelector:@selector(submitPayOffer) withObject:nil afterDelay:0.5];
 }
 }];
 [replyViewController_ showAnimated:self.view.window];

发表评论