块对象相当于C#中的匿名委托,是对一段代码的引用,@selector相当于C#中的委托,是对方法的引用。
- 创建块对象
^{ NSLog(@"This is a block"); }
- 声明块变量
void (^simpleBlock)(void);
- 变量赋值
simpleBlock = ^{ NSLog(@"This is a block"); };
- 一起写的语法
void (^simpleBlock)(void) = ^{ NSLog(@"This is a block"); };
- 对块对象的调用
simpleBlock();
-
带参数和返回值的块
double (^multiplyTwoValues)(double, double) = ^(double firstValue, double secondValue) { return firstValue * secondValue; }; double result = multiplyTwoValues(2,4); NSLog(@"The result is %f", result);
- 对作用域范围内变量的访问
可以对块外定义的变量进行访问,块外的变量会传值给块,如要传递引用,需要对变量用__block进行修饰。int anInteger = 42; void (^testBlock)(void) = ^{ NSLog(@"Integer is: %i", anInteger); }; anInteger = 84; testBlock();
上面代码输出
Integer is: 42
__block int anInteger = 42; void (^testBlock)(void) = ^{ NSLog(@"Integer is: %i", anInteger); }; anInteger = 84; testBlock();
这段代码输出
Integer is: 84
块可以作为方法的参数进行传递
方法的声明
- (void)beginTaskWithCallbackBlock:(void (^)(void))callbackBlock;
方法的实现
- (void)beginTaskWithCallbackBlock:(void (^)(void))callbackBlock { ... callbackBlock(); }
注意:块只能作为方法的最后一个参数
定义块类型
typedef void (^XYZSimpleBlock)(void);
XYZSimpleBlock anotherBlock = ^{
...
};
- (void)beginFetchWithCallbackBlock:(XYZSimpleBlock)callbackBlock { ... callbackBlock(); }
在复杂的使用是定义块类型很有用
void (^(^complexBlock)(void (^)(void)))(void) = ^ (void (^aBlock)(void)) { ... return ^{ ... }; };
XYZSimpleBlock (^betterBlock)(XYZSimpleBlock) = ^ (XYZSimpleBlock aBlock) { ... return ^{ ... }; };
定义块类型的属性
typedef void (^XYZSimpleBlock)(void); @interface XYZObject : NSObject @property (copy) XYZSimpleBlock blockProperty; @end
当捕获自身时避免Strong引用循环
@implementation XYZBlockKeeper - (void)configureBlock { self.block = ^{ [self doSomething]; // capturing a strong reference to self // creates a strong reference cycle }; } ... @end
应修改成下面的代码
- (void)configureBlock { XYZBlockKeeper * __weak weakSelf = self; self.block = ^{ [weakSelf doSomething]; // capture the weak reference // to avoid the reference cycle } }
块能遍历集合中的对象
比如在NSArray中定义了枚举的方法
- (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block;
[array enumerateObjectsUsingBlock:^ (id obj, NSUInteger idx, BOOL *stop) { if (...) { *stop = YES; } }];
也可以并发执行
[array enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^ (id obj, NSUInteger idx, BOOL *stop) { ... }];
NSDictionary也提供了类似的方法
NSDictionary *dictionary = ... [dictionary enumerateKeysAndObjectsUsingBlock:^ (id key, id obj, BOOL *stop) { NSLog(@"key: %@, value: %@", key, obj); }];