[aDictionary enumerateKeysAndObjectsUsingblock:^(id key, id value, BOOL *stop) { NSLog(@"value for key %@ is %@", key, value); if ([@"ENOUGH" isEqualToString:key]) { *stop = YES; } }];这跟Java中的匿名类有点类似。
double stopValue = 53.5; [aDictionary enumerateKeysAndObjectsUsingblock:^(id key, id value, BOOL *stop) { NSLog(@"value for key %@ is %@", key, value); if ([@"ENOUGH" isEqualToString:key] || ([value doubleValue] == stopValue)) { *stop = YES; } }];但是它们是只读的!
BOOL stopedEarly = NO; double stopValue = 53.5; [aDictionary enumerateKeysAndObjectsUsingblock:^(id key, id value, BOOL *stop) { NSLog(@"value for key %@ is %@", key, value); if ([@"ENOUGH" isEqualToString:key] || ([value doubleValue] == stopValue)) { *stop = YES; stoppedEarly = YES; // ILLEGAL! 非法 } }];除非你以__block标识本地变量:
__block BOOL stopedEarly = NO; double stopValue = 53.5; [aDictionary enumerateKeysAndObjectsUsingblock:^(id key, id value, BOOL *stop) { NSLog(@"value for key %@ is %@", key, value); if ([@"ENOUGH" isEqualToString:key] || ([value doubleValue] == stopValue)) { *stop = YES; stoppedEarly = YES; // this is legal now } }]; if (stoppedEarly) NSLog(@"I stopped logging dictionary value early!");本地变量也可以是对象实例,但是我们只能以setter、getter方式来访问。
NSString *stopKey = [@"Enough" uppercaseString]; __block BOOL stopedEarly = NO; double stopValue = 53.5; [aDictionary enumerateKeysAndObjectsUsingblock:^(id key, id value, BOOL *stop) { NSLog(@"value for key %@ is %@", key, value); if ([stopKey isEqualToString:key] || ([value doubleValue] == stopValue)) { *stop = YES; stoppedEarly = YES; // this is legal now } }]; if (stoppedEarly) NSLog(@"I stopped logging dictionary value early!");block中将自动持有stopKey的强引用(strong)指针,直到block被释放。
typedef double (^unary_operation_t)(double op);以上代码声明了一个"unary_operation_t"的类型,该类型对应的变量可以存储block。
unary_operation_t square; square = ^(double operand) { // square变量的值是一个block return operand * operand; }然后用以下方式来使用square变量:
double squareOfFive = square(5.0); // 这句代码执行后squareOfFile的值是25.0并不需要强制使用typedef,比如以下代码也是创建square的合法方式:
double (^square)(double op) = ^(double op) {return op * op;};我们可以用以下方式来使用unary_operation_t:
@property (nonatomic, strong) NSMutableDictionary *unaryOperations;然后像这样实现一个方法:
typedef double (^unary_operation_t)(double op); -(void)addUnaryOperation:(NSString *)op whichExecutesBlock:(unary_operation_t)opBlock { self.unaryOperations[op] = opBlock; }注意block某种程度上可以被当作对象(e.g. adding it to a dictionary).
-(double)performOperation:(NSString *)operation onOperand:(double)operand { unary_operation_t unaryOp = self.unaryOperations[operation]; if(unaryOp) { double result = unaryOp(operand); } ... }我们并不总是需要typedef,当一个block是一个方法的参数并且需要马上使用的时候,
-(void)enumerateKeyAndObjectUsingBlock:(void (^)(id key, id obj, BOOL *stop))block;以上方法定义的block没有名字,除了没有名字之外,语法其实跟使用typedef是一样的.
typedef void (^enumeratingBlock)(id key, id obj, BOOL *stop);其中enumeratingBlock这部分在方法参数中并没有使用。
[UIView animateWithDuration:5.0 animations:^() { view.opacity = 0.5; }];可以写成这样:
[UIView animateWithDuration:5.0 animations:^ { view.opacity = 0.5; }];与此类似的还有返回类型,返回类型经常可以被推断出来,此时返回类型是可以省略的。
NSSet * mySet = ...; NSSet * matches = [mySet objectsPassingTest:^(id obj, ...) { return [obj isKindOfClass:[UIView class]]; }];return语句表面此block返回的是BOOL类型,所以在定义以上匿名block时没有使用返回类型。
@property (nonatomic, strong) NSMutableArray * myBlocks; // array for blocks你可以做以下事情
[self.myBlocks addObject:^{ [self doSomething]; }];非常简洁有木有!
void (^doit)(void) = self.myBlocks[0]; doit();但是这样是有危险的。
[self .myBlocks addObject:^ { [self doSomething]; }];所以这个block持有self的strong指针,但是请注意self同时也持有block的strong指针,
__weak MyClass *weakSelf = self; //虽然even是strong类型的,weakSelf是weak类型的。
现在如果我们在block中引用weakSelf,block将不会以strong方式引用到self:
[self.myBlocks addObject:^ { [weakSelf doSomething]; }现在我们不再有内存循环引用了,只要外部什么地方持有了self的strong指针,