当前位置:编程学习 > C/C++ >>

Using Blocks in iOS 4: The Basics

iOS 4 introduces one new feature that will fundamentally change the way you program ingeneral: blocks. Blocks are an extension to the C language and thus fully supported inObjective-C. If you're coming from a programming language such as Ruby, Python, or Lisp,then you know the power of blocks. Simply put, blocks let you encapsulate chunks of codeand pass them around like any other object. It's a different style of programming thatyou'll want to become familiar with to take advantage of new APIs in iOS 4.

Let's start by taking a look at two examples of where you might use blocks in iOS 4: view animations and enumeration.

Blocks By Example
As our first example, suppose we're creating a card game and we want to animate slidinga card from the dealer's hand to a player's position. Fortunately, the UIKit frameworkdoes all the heavy lifting when it comes to performing animations. What gets animated,however, is specific to your application. You specify what will be animated in a block,and toss it over to theanimateWithDuration:animations: method, like so:

[cpp]
[UIView animateWithDuration:2.0 
    animations:^ { 
        self.cardView.alpha = 1.0; 
        self.cardView.frame = CGRectMake(176.0, 258.0, 72.0, 96.0); 
        self.cardView.transform = CGAffineTransformMakeRotation(M_PI); 
    } 
]; 
When this animation block is run, our card view will animate in three ways: change itsalpha to fade in the card, change its position to the lower-right of the frame (theplayer's position), and rotate itself 180 degrees (to give the dealer style points).

Our second example of blocks is to enumerate over a collection of cards and print the name and index of each card. You could use afor loop for this, but in iOS 4 the NSArray class has a handyenumerateObjectsUsingBlock: method that takes a block. Here's how to use it:

[cpp]  
NSArray *cards = 
    [NSArrayarrayWithObjects:@"Jack", @"Queen", @"King", @"Ace", nil]; 
  
[cards enumerateObjectsUsingBlock:^(idobject, NSUIntegerindex, BOOL *stop) { 
    NSLog(@"%@ card at index %d", object, index); 
}]; 
As we'll explore a bit more later, this block takes three parameters: the currentelement in the array, its index, and a flag to signal whether enumeration should stop(which we've ignored). TheenumerateObjectsUsingBlock: method calls theblock once for each element in the array and supplies the parameters.

So the upshot of using blocks in your Mac and iOS apps is that they allow you to attach arbitrary code to Apple-provided methods. Although similar in concept to delegation, passing short inline blocks of code to methods is often more convenient and elegant.

That's a good start, but it's important to understand what's going on. Whenever I'm learning anything new, I like to break it down into its simplest elements, get comfortable with how they work, and then (hopefully) put everything back together again. That way I feel confident with the code I write and can quickly debug any problems. So let's step back for a minute and learn how to declare and call basic blocks.

Block Basics
A block is simply a chunk of executable code. For example, here's a block that prints the current date and time:

[cpp] 
^ { 
    NSDate*date = [NSDatedate]; 
    NSLog(@"The date and time is %@", date); 
}; 
The caret () introduces a block literal and the curly braces enclose statements that make up the body of the block. You can think of a block as being similar to an anonymous function.

So if it's anonymous, how exactly do we use this block? The most common way to use ablock is to pass it to a method that in turn calls the block. We saw how to do thatearlier with animations and enumeration. The other way to use a block is to assign it toa block variable and call the block directly. Here's how to assign our block to a blockvariable callednow:

[cpp] 
void (^now)(void) = ^ { 
    NSDate*date = [NSDatedate]; 
    NSLog(@"The date and time is %@", date); 
}; 
Here's where things get funky. The syntax for declaring a block variable takes somegetting used to. If you've used function pointers, block variables will look familiar. On the right-hand side of the assignment we have our block literal (nothing new there).On the left-hand side of the assignment we've declared a block variable callednow.


The name of the block variable is always preceded by a and in parentheses. Block variables have an associated type. In this case, thenow variable can reference any block that returns no value (the firstvoid) and takes no parameters (the void in parentheses). Ourblock conforms to this type, so we can safely assign it to thenowvariable.

Once we have a block variable in scope, calling the block is just like calling a function. Here's how we call our block:

[cpp]
now(); 
You could declare the block variable in a C function or Objective-C method, for example,and then call it in the same scope. When the block executes, it prints the current dateand time. So far, so good.

Blocks Are Closures
If that's all there was to blocks, they'd be just like functions. But it turns out that blocks are more than just chunks of executable code. Blocks also capture their surrounding state. That is, blocks are closures: theyclose around variables that are in scope at the time the block is declared. To illustrate, let's change the previous example around a bit by moving the initialization of the date outside the block:

[cpp]
NSDate *date = [NSDate date]; 
  
void (^now)(void) = ^ { 
    NSLog(@"The date and time is %@", date); 
}; 
  
now(); 
When you call this block the first time, it behaves exactly like the previous version: it prints the current date and time. But there's a significant difference here. It becomes evident when we change the date and then call the block again:

[cpp] 
sleep(5); 
  
date = [NSDatedate]; 
   
now(); 
Even though we've changed the date variable referenced by the block, whenthe block is called it still prints the original date and time. It's as if time stoodstill when the block was declared. And that's effectively what happens. As executionpasses over the point where the block is declared, the block takes a (read-only)snapshot of all the variables in scope that the block uses. You can think of the valueof thedate variable as being frozen inside the block. Therefore, wheneverthe block is called—immediately, 5 seconds later, or just before the appquits—it always prints the original date and time.

Now, the fact that blocks are closures is not particularly interesting in this example. After all, you could have just passed the date as a parameter to the block (more on that next). But closures become really useful when you start passing blocks around to methods because the captured state goes along for the ride.

Block Parameters
Just like functions, blocks can take parameters and return values. Say, for example, we want a block that takes a given number and returns the result of tripling th

补充:软件开发 , C++ ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,