CG@CPPBLOG

/*=========================================*/
随笔 - 76, 文章 - 39, 评论 - 137, 引用 - 0
数据加载中……

用OBJC编程 7 - Working with Blocks

用OBJC编程 7 - Working with Blocks

Block 是语言级别的特性。它是一个OBJC的对象,可以被加入容器如NSArray或NSDictionary。它可以捕获所处作用域的数值,非常类似其它语言的closure或者lambda。

语法
^{
    NSLog(@"This is a block");
}

可以像函数指针那样声明一个变量来持有这个block
void (^simpleBlock)(void);
simpleBlock = ^{
   NSLog(@"This is a block");
}; // 注意这里有一个分号

也可以这样写
void (^simpleBlock)(void= ^{
    NSLog(@"This is a block");
};

调用这个block
simpleBlock();

带上参数和返回值
^double (double firstValue, double secondValue){
    
return firstValue*secondValue;
}
// ,,,,,,,,,,,
double (^multiplyTwoValues)(doubledouble= 
    
^(double firstValue, double secondValue) { // 返回值类型可以省略
          return firstValue*secondValue;
     };

double result = multiplyTwoValues(2,4);
NSLog(@"The result is %f", result);

捕获Enclosing Scope内的值,一旦捕获,这个值就不会变化,即便后续改变这个值
-(void)testMethod{
  
int anInteger = 42;
  
void (^testBlock)(void= ^{
       NSLog(@"Integer is: %i", anInteger);
  }
  anInteger = 84;
  testBlock(); // 仍然输出42
}

使用__block
__block int anInteger = 42;
void (^testBlock)(void= ^{
  NSLog(@"Integer is: %i", anInteger);
};
anInteger = 84:
testBlock();  // output 84;

// ,,,,,,,,,,,,,

_block int anInteger = 42;
void (^testBlock)(void= ^{
  NSLog(@"Integer is: %i", anInteger); // output 42
  anInteger = 100;
};

testBlock();
NSLog(@"Value of original variable is now: %i", anInteger); // output 100;

通过参数传递Block,例如实现一个回调
-(IBAction)fetchRemoveInformation:(id)sender{
  [self showProgressIndicator];
  XYZWebTask *task = //,,,

  [task beginTaskWithCallbackBlock:^{
        [self hideProgressIndicator];
      }];
}

// beginTaskWithCallbackBlock 的定义是这样的

-(void)beginTaskWithCallbackBlock:(void)(^)(void))callbackBlock{
  
//,,,
  callbackBlock();
}

最佳实践是将block作为最后一个参数,这样便于阅读。

也可以使用typedef简化语法
typedef void (^XYZSimpleBlock)(void);
//,,,,,,,,,,,,,,,
XYZSimpleBlock anotherBlock = ^/*,,,*/ };
//,,,,,,,,,,,,
-(void)beginFetchWithCallbackBlock:(XYZSimpleBlock)callbackBlock{
    
//,,,,
    callbackBlock();
}

可以将block作为属性
@interface XYZObject : NSObject
@property (copy) void (^blockProperty)(void); // 必须使用copy
@end
//,,,,,,,,,,,,,,
self.blockProperty = ^/* ,,, */ };
self.blockProperty();

避免强引用循环
在block里捕获self,诸如在一个callback block里,会引入内存管理问题。block会会维护一个捕获对象的强引用,包括self
@interface XYZBlockKeeper : NSObject
@property (copy) void (^block)(void);
@end
////////////////////////
@implementation XYZBlockKeeper
-(void)configureBlock{
  self.block = ^{
    [self doSomething];    // 捕获了一个self的强引用
                           
// 建立了一个强引用循环
  }
}
@end

上述代码会产生一个编译警告,为了避免这种情况,最佳实践是捕获一个self的弱引用
-(void)configureBlock{
   XYZBlockKeeper * __weak weakSelf = self;
   self.block = ^ {
      [weakSelf doSomething];
   };
}

block可以简化枚举(略)
block可以简化并发任务(略)



posted on 2013-11-21 19:20 cuigang 阅读(299) 评论(0)  编辑 收藏 引用 所属分类: OBJC


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理