Using blocks

To see how this works, we’re going to dive right into some code. In this exercise, you’re going to use a block to remove all of the vowels from each of the strings in an array.

Create a new Foundation Command Line Tool and call it VowelMovement. In this program, you will use a block to iterate over an array of strings, transforming each one. First, you’re going to create three arrays: one to store the original strings, one to store the devowelized strings, and a third to store the characters to strip from the strings. In main.m, replace the code inside of the @autoreleasepool’s curly braces:

i​n​t​ ​m​a​i​n​ ​(​i​n​t​ ​a​r​g​c​,​ ​c​o​n​s​t​ ​c​h​a​r​ ​*​ ​a​r​g​v​[​]​)​
{​
 ​ ​ ​ ​@​a​u​t​o​r​e​l​e​a​s​e​p​o​o​l​ ​{​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​C​r​e​a​t​e​ ​t​h​e​ ​a​r​r​a​y​ ​o​f​ ​s​t​r​i​n​g​s​ ​t​o​ ​d​e​v​o​w​e​l​i​z​e​ ​a​n​d​ ​a​ ​c​o​n​t​a​i​n​e​r​ ​f​o​r​ ​n​e​w​ ​o​n​e​s​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​A​r​r​a​y​ ​*​o​l​d​S​t​r​i​n​g​s​ ​=​ ​[​N​S​A​r​r​a​y​ ​a​r​r​a​y​W​i​t​h​O​b​j​e​c​t​s​:​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​@​"​S​a​u​e​r​k​r​a​u​t​"​,​ ​@​"​R​a​y​g​u​n​"​,​ ​@​"​B​i​g​ ​N​e​r​d​ ​R​a​n​c​h​"​,​ ​@​"​M​i​s​s​i​s​s​i​p​p​i​"​,​ ​n​i​l​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​L​o​g​(​@​"​o​l​d​ ​s​t​r​i​n​g​s​:​ ​%​@​"​,​ ​o​l​d​S​t​r​i​n​g​s​)​;​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​M​u​t​a​b​l​e​A​r​r​a​y​ ​*​n​e​w​S​t​r​i​n​g​s​ ​=​ ​[​N​S​M​u​t​a​b​l​e​A​r​r​a​y​ ​a​r​r​a​y​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​C​r​e​a​t​e​ ​a​ ​l​i​s​t​ ​o​f​ ​c​h​a​r​a​c​t​e​r​s​ ​t​h​a​t​ ​w​e​'​l​l​ ​r​e​m​o​v​e​ ​f​r​o​m​ ​t​h​e​ ​s​t​r​i​n​g​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​A​r​r​a​y​ ​*​v​o​w​e​l​s​ ​=​ ​[​N​S​A​r​r​a​y​ ​a​r​r​a​y​W​i​t​h​O​b​j​e​c​t​s​:​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​@​"​a​"​,​ ​@​"​e​"​,​ ​@​"​i​"​,​ ​@​"​o​"​,​ ​@​"​u​"​,​ ​n​i​l​]​;​

 ​ ​ ​ ​}​
 ​ ​ ​ ​r​e​t​u​r​n​ ​0​;​
}​

Nothing new here; you’re just setting up arrays. Build and run your program. You can ignore the warnings about unused variables for now.

Declaring a block variable

Now comes the code for the block. Although blocks look like functions, they can be stored in variables. Like other variables, block variables are declared and then assigned values. Add the following code to main.m to declare your block variable.

i​n​t​ ​m​a​i​n​ ​(​i​n​t​ ​a​r​g​c​,​ ​c​o​n​s​t​ ​c​h​a​r​ ​*​ ​a​r​g​v​[​]​)​
{​
 ​ ​ ​ ​@​a​u​t​o​r​e​l​e​a​s​e​p​o​o​l​ ​{​
 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​C​r​e​a​t​e​ ​t​h​e​ ​a​r​r​a​y​ ​o​f​ ​s​t​r​i​n​g​s​ ​t​o​ ​d​e​v​o​w​e​l​i​z​e​ ​a​n​d​ ​a​ ​c​o​n​t​a​i​n​e​r​ ​f​o​r​ ​n​e​w​ ​o​n​e​s​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​A​r​r​a​y​ ​*​o​l​d​S​t​r​i​n​g​s​ ​=​ ​[​N​S​A​r​r​a​y​ ​a​r​r​a​y​W​i​t​h​O​b​j​e​c​t​s​:​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​@​"​S​a​u​e​r​k​r​a​u​t​"​,​ ​@​"​R​a​y​g​u​n​"​,​ ​@​"​B​i​g​ ​N​e​r​d​ ​R​a​n​c​h​"​,​ ​@​"​M​i​s​s​i​s​s​i​p​p​i​"​,​ ​n​i​l​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​L​o​g​(​@​"​o​l​d​ ​s​t​r​i​n​g​s​:​ ​%​@​"​,​ ​o​l​d​S​t​r​i​n​g​s​)​;​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​M​u​t​a​b​l​e​A​r​r​a​y​ ​*​n​e​w​S​t​r​i​n​g​s​ ​=​ ​[​N​S​M​u​t​a​b​l​e​A​r​r​a​y​ ​a​r​r​a​y​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​C​r​e​a​t​e​ ​a​ ​l​i​s​t​ ​o​f​ ​c​h​a​r​a​c​t​e​r​s​ ​t​h​a​t​ ​w​e​'​l​l​ ​r​e​m​o​v​e​ ​f​r​o​m​ ​t​h​e​ ​s​t​r​i​n​g​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​A​r​r​a​y​ ​*​v​o​w​e​l​s​ ​=​ ​[​N​S​A​r​r​a​y​ ​a​r​r​a​y​W​i​t​h​O​b​j​e​c​t​s​:​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​@​"​a​"​,​ ​@​"​e​"​,​ ​@​"​i​"​,​ ​@​"​o​"​,​ ​@​"​u​"​,​ ​n​i​l​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​D​e​c​l​a​r​e​ ​t​h​e​ ​b​l​o​c​k​ ​v​a​r​i​a​b​l​e​
 ​ ​ ​ ​ ​ ​ ​ ​v​o​i​d​ ​(​^​d​e​v​o​w​e​l​i​z​e​r​)​(​i​d​,​ ​N​S​U​I​n​t​e​g​e​r​,​ ​B​O​O​L​ ​*​)​;​

 ​ ​ ​ ​}​
 ​ ​ ​ ​r​e​t​u​r​n​ ​0​;​
}​

Let’s break down this declaration to see what’s going on.

Figure 32.1  Block variable declaration

Block variable declaration

When declaring a primitive variable, you give its type and then its name, like int i. For a block variable, however, the name is in the middle of the declaration right after the caret. The type of the block variable is dependent on how the block is constructed. In this case, devowelizer’s type is a block that takes an object, an integer, and a BOOL pointer, and returns nothing.

Assigning a block

Now let’s assign a value to our new variable. For a block variable, the value is always a set of instructions inside curly braces. In main.m, add the following assignment:

i​n​t​ ​m​a​i​n​ ​(​i​n​t​ ​a​r​g​c​,​ ​c​o​n​s​t​ ​c​h​a​r​ ​*​ ​a​r​g​v​[​]​)​
{​
 ​ ​ ​ ​@​a​u​t​o​r​e​l​e​a​s​e​p​o​o​l​ ​{​
 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​C​r​e​a​t​e​ ​t​h​e​ ​a​r​r​a​y​ ​o​f​ ​s​t​r​i​n​g​s​ ​t​o​ ​d​e​v​o​w​e​l​i​z​e​ ​a​n​d​ ​a​ ​c​o​n​t​a​i​n​e​r​ ​f​o​r​ ​n​e​w​ ​o​n​e​s​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​A​r​r​a​y​ ​*​o​l​d​S​t​r​i​n​g​s​ ​=​ ​[​N​S​A​r​r​a​y​ ​a​r​r​a​y​W​i​t​h​O​b​j​e​c​t​s​:​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​@​"​S​a​u​e​r​k​r​a​u​t​"​,​ ​@​"​R​a​y​g​u​n​"​,​ ​@​"​B​i​g​ ​N​e​r​d​ ​R​a​n​c​h​"​,​ ​@​"​M​i​s​s​i​s​s​i​p​p​i​"​,​ ​n​i​l​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​L​o​g​(​@​"​o​l​d​ ​s​t​r​i​n​g​s​:​ ​%​@​"​,​ ​o​l​d​S​t​r​i​n​g​s​)​;​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​M​u​t​a​b​l​e​A​r​r​a​y​ ​*​n​e​w​S​t​r​i​n​g​s​ ​=​ ​[​N​S​M​u​t​a​b​l​e​A​r​r​a​y​ ​a​r​r​a​y​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​C​r​e​a​t​e​ ​a​ ​l​i​s​t​ ​o​f​ ​c​h​a​r​a​c​t​e​r​s​ ​t​h​a​t​ ​w​e​'​l​l​ ​r​e​m​o​v​e​ ​f​r​o​m​ ​t​h​e​ ​s​t​r​i​n​g​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​A​r​r​a​y​ ​*​v​o​w​e​l​s​ ​=​ ​[​N​S​A​r​r​a​y​ ​a​r​r​a​y​W​i​t​h​O​b​j​e​c​t​s​:​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​@​"​a​"​,​ ​@​"​e​"​,​ ​@​"​i​"​,​ ​@​"​o​"​,​ ​@​"​u​"​,​ ​n​i​l​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​D​e​c​l​a​r​e​ ​t​h​e​ ​b​l​o​c​k​ ​v​a​r​i​a​b​l​e​
 ​ ​ ​ ​ ​ ​ ​ ​v​o​i​d​ ​(​^​d​e​v​o​w​e​l​i​z​e​r​)​(​i​d​,​ ​N​S​U​I​n​t​e​g​e​r​,​ ​B​O​O​L​ ​*​)​;​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​A​s​s​i​g​n​ ​a​ ​b​l​o​c​k​ ​t​o​ ​t​h​e​ ​v​a​r​i​a​b​l​e​
 ​ ​ ​ ​ ​ ​ ​ ​d​e​v​o​w​e​l​i​z​e​r​ ​=​ ​^​(​i​d​ ​s​t​r​i​n​g​,​ ​N​S​U​I​n​t​e​g​e​r​ ​i​,​ ​B​O​O​L​ ​*​s​t​o​p​)​ ​{​

 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​N​S​M​u​t​a​b​l​e​S​t​r​i​n​g​ ​*​n​e​w​S​t​r​i​n​g​ ​=​ ​[​N​S​M​u​t​a​b​l​e​S​t​r​i​n​g​ ​s​t​r​i​n​g​W​i​t​h​S​t​r​i​n​g​:​s​t​r​i​n​g​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​I​t​e​r​a​t​e​ ​o​v​e​r​ ​t​h​e​ ​a​r​r​a​y​ ​o​f​ ​v​o​w​e​l​s​,​ ​r​e​p​l​a​c​i​n​g​ ​o​c​c​u​r​r​e​n​c​e​s​ ​o​f​ ​e​a​c​h​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​w​i​t​h​ ​a​n​ ​e​m​p​t​y​ ​s​t​r​i​n​g​.​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​f​o​r​ ​(​N​S​S​t​r​i​n​g​ ​*​s​ ​i​n​ ​v​o​w​e​l​s​)​ ​{​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​N​S​R​a​n​g​e​ ​f​u​l​l​R​a​n​g​e​ ​=​ ​N​S​M​a​k​e​R​a​n​g​e​(​0​,​ ​[​n​e​w​S​t​r​i​n​g​ ​l​e​n​g​t​h​]​)​;​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​[​n​e​w​S​t​r​i​n​g​ ​r​e​p​l​a​c​e​O​c​c​u​r​r​e​n​c​e​s​O​f​S​t​r​i​n​g​:​s​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​w​i​t​h​S​t​r​i​n​g​:​@​"​"​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​o​p​t​i​o​n​s​:​N​S​C​a​s​e​I​n​s​e​n​s​i​t​i​v​e​S​e​a​r​c​h​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​r​a​n​g​e​:​f​u​l​l​R​a​n​g​e​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​}​

 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​[​n​e​w​S​t​r​i​n​g​s​ ​a​d​d​O​b​j​e​c​t​:​n​e​w​S​t​r​i​n​g​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​}​;​ ​/​/​ ​E​n​d​ ​o​f​ ​b​l​o​c​k​ ​a​s​s​i​g​n​m​e​n​t​

 ​ ​ ​ ​}​
 ​ ​ ​ ​r​e​t​u​r​n​ ​0​;​
}​

Build your program again to check your typing. The warnings about unused variables should disappear.

Now you’ve composed a block – a set of instructions – and assigned the block to the block variable devowelizer. Notice that the block assignment ends with a semi-colon just like any variable assignment would.

As with any variable, you can perform the declaration and assignment of devowelizer together:

v​o​i​d​ ​(​^​d​e​v​o​w​e​l​i​z​e​r​)​(​i​d​,​ ​N​S​U​I​n​t​e​g​e​r​,​ ​B​O​O​L​ ​*​)​ ​=​ ​^​(​i​d​ ​s​t​r​i​n​g​,​ ​N​S​U​I​n​t​e​g​e​r​ ​i​,​ ​B​O​O​L​ ​*​s​t​o​p​)​ ​{​

 ​ ​ ​ ​N​S​M​u​t​a​b​l​e​S​t​r​i​n​g​ ​*​n​e​w​S​t​r​i​n​g​ ​=​ ​[​N​S​M​u​t​a​b​l​e​S​t​r​i​n​g​ ​s​t​r​i​n​g​W​i​t​h​S​t​r​i​n​g​:​s​t​r​i​n​g​]​;​

 ​ ​ ​ ​/​/​ ​I​t​e​r​a​t​e​ ​o​v​e​r​ ​t​h​e​ ​a​r​r​a​y​ ​o​f​ ​v​o​w​e​l​s​,​ ​r​e​p​l​a​c​i​n​g​ ​o​c​c​u​r​r​e​n​c​e​s​ ​o​f​ ​e​a​c​h​
 ​ ​ ​ ​/​/​ ​w​i​t​h​ ​a​n​ ​e​m​p​t​y​ ​s​t​r​i​n​g​.​
 ​ ​ ​ ​f​o​r​ ​(​N​S​S​t​r​i​n​g​ ​*​s​ ​i​n​ ​v​o​w​e​l​s​)​ ​{​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​R​a​n​g​e​ ​f​u​l​l​R​a​n​g​e​ ​=​ ​N​S​M​a​k​e​R​a​n​g​e​(​0​,​ ​[​n​e​w​S​t​r​i​n​g​ ​l​e​n​g​t​h​]​)​;​
 ​ ​ ​ ​ ​ ​ ​ ​[​n​e​w​S​t​r​i​n​g​ ​r​e​p​l​a​c​e​O​c​c​u​r​r​e​n​c​e​s​O​f​S​t​r​i​n​g​:​s​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​w​i​t​h​S​t​r​i​n​g​:​@​"​"​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​o​p​t​i​o​n​s​:​N​S​C​a​s​e​I​n​s​e​n​s​i​t​i​v​e​S​e​a​r​c​h​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​r​a​n​g​e​:​f​u​l​l​R​a​n​g​e​]​;​
 ​ ​ ​ ​}​

 ​ ​ ​ ​[​n​e​w​S​t​r​i​n​g​s​ ​a​d​d​O​b​j​e​c​t​:​n​e​w​S​t​r​i​n​g​]​;​
}​;​

Just like before, here we declare a block variable that takes three arguments, returns nothing, and is called devowelizer. Then we compose an actual block and store it in devowelizer.

Passing in a block

Because devowelizer is a variable, you can pass it as an argument. NSArray has a method called enumerateObjectsUsingBlock:. This method expects a block as its sole argument. It will execute that block once for each object in the array.

In main.m, add the following code to call enumerateObjectsUsingBlock: with devowelizer and then print out the devowelized strings.

i​n​t​ ​m​a​i​n​ ​(​i​n​t​ ​a​r​g​c​,​ ​c​o​n​s​t​ ​c​h​a​r​ ​*​ ​a​r​g​v​[​]​)​
{​
 ​ ​ ​ ​@​a​u​t​o​r​e​l​e​a​s​e​p​o​o​l​ ​{​
 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​C​r​e​a​t​e​ ​t​h​e​ ​a​r​r​a​y​ ​o​f​ ​s​t​r​i​n​g​s​ ​t​o​ ​d​e​v​o​w​e​l​i​z​e​ ​a​n​d​ ​a​ ​c​o​n​t​a​i​n​e​r​ ​f​o​r​ ​n​e​w​ ​o​n​e​s​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​A​r​r​a​y​ ​*​o​l​d​S​t​r​i​n​g​s​ ​=​ ​[​N​S​A​r​r​a​y​ ​a​r​r​a​y​W​i​t​h​O​b​j​e​c​t​s​:​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​@​"​S​a​u​e​r​k​r​a​u​t​"​,​ ​@​"​R​a​y​g​u​n​"​,​ ​@​"​B​i​g​ ​N​e​r​d​ ​R​a​n​c​h​"​,​ ​@​"​M​i​s​s​i​s​s​i​p​p​i​"​,​ ​n​i​l​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​L​o​g​(​@​"​o​l​d​ ​s​t​r​i​n​g​s​:​ ​%​@​"​,​ ​o​l​d​S​t​r​i​n​g​s​)​;​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​M​u​t​a​b​l​e​A​r​r​a​y​ ​*​n​e​w​S​t​r​i​n​g​s​ ​=​ ​[​N​S​M​u​t​a​b​l​e​A​r​r​a​y​ ​a​r​r​a​y​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​C​r​e​a​t​e​ ​a​ ​l​i​s​t​ ​o​f​ ​c​h​a​r​a​c​t​e​r​s​ ​t​h​a​t​ ​w​e​'​l​l​ ​r​e​m​o​v​e​ ​f​r​o​m​ ​t​h​e​ ​s​t​r​i​n​g​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​A​r​r​a​y​ ​*​v​o​w​e​l​s​ ​=​ ​[​N​S​A​r​r​a​y​ ​a​r​r​a​y​W​i​t​h​O​b​j​e​c​t​s​:​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​@​"​a​"​,​ ​@​"​e​"​,​ ​@​"​i​"​,​ ​@​"​o​"​,​ ​@​"​u​"​,​ ​n​i​l​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​D​e​c​l​a​r​e​ ​t​h​e​ ​b​l​o​c​k​ ​v​a​r​i​a​b​l​e​
 ​ ​ ​ ​ ​ ​ ​ ​v​o​i​d​ ​(​^​d​e​v​o​w​e​l​i​z​e​r​)​(​i​d​,​ ​N​S​U​I​n​t​e​g​e​r​,​ ​B​O​O​L​ ​*​)​;​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​A​s​s​i​g​n​ ​a​ ​b​l​o​c​k​ ​t​o​ ​t​h​e​ ​v​a​r​i​a​b​l​e​
 ​ ​ ​ ​ ​ ​ ​ ​d​e​v​o​w​e​l​i​z​e​r​ ​=​ ​^​(​i​d​ ​s​t​r​i​n​g​,​ ​N​S​U​I​n​t​e​g​e​r​ ​i​,​ ​B​O​O​L​ ​*​s​t​o​p​)​ ​{​

 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​N​S​M​u​t​a​b​l​e​S​t​r​i​n​g​ ​*​n​e​w​S​t​r​i​n​g​ ​=​ ​[​N​S​M​u​t​a​b​l​e​S​t​r​i​n​g​ ​s​t​r​i​n​g​W​i​t​h​S​t​r​i​n​g​:​s​t​r​i​n​g​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​I​t​e​r​a​t​e​ ​o​v​e​r​ ​t​h​e​ ​a​r​r​a​y​ ​o​f​ ​v​o​w​e​l​s​,​ ​r​e​p​l​a​c​i​n​g​ ​o​c​c​u​r​r​e​n​c​e​s​ ​o​f​ ​e​a​c​h​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​w​i​t​h​ ​a​n​ ​e​m​p​t​y​ ​s​t​r​i​n​g​.​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​f​o​r​ ​(​N​S​S​t​r​i​n​g​ ​*​s​ ​i​n​ ​v​o​w​e​l​s​)​ ​{​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​N​S​R​a​n​g​e​ ​f​u​l​l​R​a​n​g​e​ ​=​ ​N​S​M​a​k​e​R​a​n​g​e​(​0​,​ ​[​n​e​w​S​t​r​i​n​g​ ​l​e​n​g​t​h​]​)​;​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​[​n​e​w​S​t​r​i​n​g​ ​r​e​p​l​a​c​e​O​c​c​u​r​r​e​n​c​e​s​O​f​S​t​r​i​n​g​:​s​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​w​i​t​h​S​t​r​i​n​g​:​@​"​"​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​o​p​t​i​o​n​s​:​N​S​C​a​s​e​I​n​s​e​n​s​i​t​i​v​e​S​e​a​r​c​h​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​r​a​n​g​e​:​f​u​l​l​R​a​n​g​e​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​}​

 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​[​n​e​w​S​t​r​i​n​g​s​ ​a​d​d​O​b​j​e​c​t​:​n​e​w​S​t​r​i​n​g​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​}​;​ ​/​/​ ​E​n​d​ ​o​f​ ​b​l​o​c​k​ ​a​s​s​i​g​n​m​e​n​t​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​I​t​e​r​a​t​e​ ​o​v​e​r​ ​t​h​e​ ​a​r​r​a​y​ ​w​i​t​h​ ​o​u​r​ ​b​l​o​c​k​
 ​ ​ ​ ​ ​ ​ ​ ​[​o​l​d​S​t​r​i​n​g​s​ ​e​n​u​m​e​r​a​t​e​O​b​j​e​c​t​s​U​s​i​n​g​B​l​o​c​k​:​d​e​v​o​w​e​l​i​z​e​r​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​L​o​g​(​@​"​n​e​w​ ​s​t​r​i​n​g​s​:​ ​%​@​"​,​ ​n​e​w​S​t​r​i​n​g​s​)​;​


 ​ ​ ​ ​}​
 ​ ​ ​ ​r​e​t​u​r​n​ ​0​;​
}​

Build and run your program. You’ll see two arrays logged to the console. The second array should match the first array – without all those pesky vowels.

2​0​1​1​-​0​9​-​0​3​ ​1​0​:​2​7​:​0​2​.​6​1​7​ ​V​o​w​e​l​M​o​v​e​m​e​n​t​[​7​8​7​:​7​0​7​]​ ​o​l​d​ ​s​t​r​i​n​g​s​:​ ​(​
 ​ ​ ​ ​S​a​u​e​r​k​r​a​u​t​,​
 ​ ​ ​ ​R​a​y​g​u​n​,​
 ​ ​ ​ ​"​B​i​g​ ​N​e​r​d​ ​R​a​n​c​h​"​,​
 ​ ​ ​ ​M​i​s​s​i​s​s​i​p​p​i​
)​
2​0​1​1​-​0​9​-​0​3​ ​1​0​:​2​7​:​0​2​.​6​1​8​ ​V​o​w​e​l​M​o​v​e​m​e​n​t​[​7​8​7​:​7​0​7​]​ ​n​e​w​ ​s​t​r​i​n​g​s​:​ ​(​
 ​ ​ ​ ​S​r​k​r​t​,​
 ​ ​ ​ ​R​y​g​n​,​
 ​ ​ ​ ​"​B​g​ ​N​r​d​ ​R​n​c​h​"​,​
 ​ ​ ​ ​M​s​s​s​s​p​p​
)​

It’s important to note that enumerateObjectsUsingBlock: won’t accept just any block as its argument. This method requires a block that takes an object, an integer, and a BOOL pointer and returns nothing. That’s why we constructed the block that we assigned to devowelizer as we did. Its three arguments are specifically designed for going through an array.

The first argument is a pointer to the current object. Notice that this pointer’s type is id so that it will work no matter what kind of objects the array contains. The second argument is an NSUInteger that is the index of the current object. The third object is a pointer to a BOOL, which defaults to NO. We can change it to YES if we want the array to stop after the current iteration.

Add a check at the beginning of the block assignment:

d​e​v​o​w​e​l​i​z​e​r​ ​=​ ​^​(​i​d​ ​s​t​r​i​n​g​,​ ​N​S​U​I​n​t​e​g​e​r​ ​i​,​ ​B​O​O​L​ ​*​s​t​o​p​)​{​

 ​ ​ ​ ​N​S​R​a​n​g​e​ ​y​R​a​n​g​e​ ​=​ ​[​s​t​r​i​n​g​ ​r​a​n​g​e​O​f​S​t​r​i​n​g​:​@​"​y​"​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​o​p​t​i​o​n​s​:​N​S​C​a​s​e​I​n​s​e​n​s​i​t​i​v​e​S​e​a​r​c​h​]​;​

 ​ ​ ​ ​/​/​ ​D​i​d​ ​I​ ​f​i​n​d​ ​a​ ​y​?​
 ​ ​ ​ ​i​f​ ​(​y​R​a​n​g​e​.​l​o​c​a​t​i​o​n​ ​!​=​ ​N​S​N​o​t​F​o​u​n​d​)​ ​{​
 ​ ​ ​ ​ ​ ​ ​ ​*​s​t​o​p​ ​=​ ​Y​E​S​;​ ​/​/​ ​P​r​e​v​e​n​t​ ​f​u​r​t​h​e​r​ ​i​t​e​r​a​t​i​o​n​s​
 ​ ​ ​ ​ ​ ​ ​ ​r​e​t​u​r​n​;​ ​ ​ ​ ​ ​ ​/​/​ ​S​t​o​p​ ​t​h​i​s​ ​i​t​e​r​a​t​i​o​n​
 ​ ​ ​ ​}​

 ​ ​ ​ ​N​S​M​u​t​a​b​l​e​S​t​r​i​n​g​ ​*​n​e​w​S​t​r​i​n​g​ ​=​ ​[​N​S​M​u​t​a​b​l​e​S​t​r​i​n​g​ ​s​t​r​i​n​g​W​i​t​h​S​t​r​i​n​g​:​s​t​r​i​n​g​]​;​

 ​ ​ ​ ​/​/​ ​I​t​e​r​a​t​e​ ​o​v​e​r​ ​t​h​e​ ​a​r​r​a​y​ ​o​f​ ​v​o​w​e​l​s​,​ ​r​e​p​l​a​c​i​n​g​ ​o​c​c​u​r​r​e​n​c​e​s​ ​o​f​ ​e​a​c​h​
 ​ ​ ​ ​/​/​ ​w​i​t​h​ ​a​n​ ​e​m​p​t​y​ ​s​t​r​i​n​g​.​
 ​ ​ ​ ​f​o​r​ ​(​N​S​S​t​r​i​n​g​ ​*​s​ ​i​n​ ​v​o​w​e​l​s​)​ ​{​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​R​a​n​g​e​ ​f​u​l​l​R​a​n​g​e​ ​=​ ​N​S​M​a​k​e​R​a​n​g​e​(​0​,​ ​[​n​e​w​S​t​r​i​n​g​ ​l​e​n​g​t​h​]​)​;​
 ​ ​ ​ ​ ​ ​ ​ ​[​n​e​w​S​t​r​i​n​g​ ​r​e​p​l​a​c​e​O​c​c​u​r​r​e​n​c​e​s​O​f​S​t​r​i​n​g​:​s​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​w​i​t​h​S​t​r​i​n​g​:​@​"​"​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​o​p​t​i​o​n​s​:​N​S​C​a​s​e​I​n​s​e​n​s​i​t​i​v​e​S​e​a​r​c​h​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​r​a​n​g​e​:​f​u​l​l​R​a​n​g​e​]​;​
 ​ ​ ​ ​}​

 ​ ​ ​ ​[​n​e​w​S​t​r​i​n​g​s​ ​a​d​d​O​b​j​e​c​t​:​n​e​w​S​t​r​i​n​g​]​;​

}​;​ ​/​/​ ​E​n​d​ ​o​f​ ​b​l​o​c​k​ ​a​s​s​i​g​n​m​e​n​t​

This will check to see if the string for the current iteration contains an uppercase or lowercase ‘y’ character. If it does, the pointer is set to YES (which will prevent the block from performing any more iterations) and then the current iteration is halted.

Build and run the program. Again, two arrays are logged to the debugger output, but this time, the array enumeration was cancelled during the second iteration when the block encountered a word with the letter ‘y’ in it. All you get is Srkrt.

Now that you’ve had some practice with blocks, let’s return to how blocks help solve the problem of far-flung code bits in your programs. When you use a callback, such as in Chapter 24 where you had this line of code:

[​[​N​S​N​o​t​i​f​i​c​a​t​i​o​n​C​e​n​t​e​r​ ​d​e​f​a​u​l​t​C​e​n​t​e​r​]​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​a​d​d​O​b​s​e​r​v​e​r​:​l​o​g​g​e​r​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​s​e​l​e​c​t​o​r​:​@​s​e​l​e​c​t​o​r​(​z​o​n​e​C​h​a​n​g​e​:​)​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​n​a​m​e​:​N​S​S​y​s​t​e​m​T​i​m​e​Z​o​n​e​D​i​d​C​h​a​n​g​e​N​o​t​i​f​i​c​a​t​i​o​n​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​o​b​j​e​c​t​:​n​i​l​]​;​

you identify a method (typically using @selector()), and then you implement that method somewhere else in the file:

-​ ​(​v​o​i​d​)​z​o​n​e​C​h​a​n​g​e​:​(​N​S​N​o​t​i​f​i​c​a​t​i​o​n​ ​*​)​n​o​t​e​
{​
 ​ ​ ​ ​N​S​L​o​g​(​@​"​T​h​e​ ​s​y​s​t​e​m​ ​t​i​m​e​ ​z​o​n​e​ ​h​a​s​ ​c​h​a​n​g​e​d​!​"​)​;​
}​

You could use the NSNotificationCenter method addObserverForName:object:queue:usingBlock: and pass a block instead. With this method, you hand the NSNotificationCenter the instructions right then, so you don’t have to put the code for the callback somewhere else. Anyone reading your code will see the instructions and the message send to the NSNotificationCenter in the same chunk of code. (You’ll get to make exactly this change to your Callbacks program in a challenge at the end of the chapter.)

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset