Home > Articles > Programming > C/C++

  • Print
  • + Share This
This chapter is from the book

Accessing Enclosing Scope

Blocks can also access their enclosing scope. Say you wanted to print out each of the words that contains "badger." You can use a variation of the previous code, using -enumerateObjectsUsingBlock:

[array enumerateObjectsUsingBlock:
           ^(id object, NSUInteger index, BOOL *stop) {
        NSRange match = [object rangeOfString: @"badger"];
        if (match.location != NSNotFound) {
            NSLog (@"found a '%@' : %@", @"badger", object);
        }
    }];

Which would print out

  found a 'badger' : badger
  found a 'badger' : badgerific

It would be nice to be able to generalize this code so "badger" is not hard-coded. Blocks can capture the values of variables defined in the scope that contains the block. Here is a more general version:

NSString *subString = @"badger";

[array enumerateObjectsUsingBlock:
           ^(id object, NSUInteger index, BOOL *stop) {
        NSRange match = [object rangeOfString: subString];
        if (match.location != NSNotFound) {
            NSLog (@"found a '%@' : %@", subString, object);
        }
    }];

As you would expect, this also prints out

  found a 'badger' : badger
  found a 'badger' : badgerific

The subString variable does not have to be a hard-coded assignment either. It could be a value retrieved from an NSTextField or UITextField.

So, what is happening here? The compiler emits code that captures the value of any variables in the outer scope that are used inside of the block. The block, in essence, takes a snapshot of the world at this point in time. Captured local variables are treated as constant. You cannot assign to subString inside of the block; if you do, you will get an error.

Captured Objective-C objects are retained. subString therefore has been retained. It will automatically be released when the block goes away.

  • + Share This
  • 🔖 Save To Your Account