今天继续讲Objective-C的Block,讲Block作为参数传递给一个方法,实际上,这种用法是Block的主要使用场景。
下面是ios reference官方的讲解:
You Can Pass Blocks as Arguments to Methods or Functions
Each of the previous examples in this chapter invokes the block immediately after it’s defined. In practice, it’s common to pass blocks to functions or methods for invocation elsewhere. You might use Grand Central Dispatch to invoke a block in the background, for example, or define a block to represent a task to be invoked repeatedly, such as when enumerating a collection. Concurrency and enumeration are covered later in this chapter.
Blocks are also used for callbacks, defining the code to be executed when a task completes. As an example, your app might need to respond to a user action by creating an object that performs a complicated task, such as requesting information from a web service. Because the task might take a long time, you should display some kind of progress indicator while the task is occurring, then hide that indicator once the task is complete.
It would be possible to accomplish this using delegation: You’d need to create a suitable delegate protocol, implement the required method, set your object as the delegate of the task, then wait for it to call a delegate method on your object once the task finished.
Blocks make this much easier, however, because you can define the callback behavior at the time you initiate the task, like this:
- (IBAction)fetchRemoteInformation:(id)sender {
[self showProgressIndicator];
XYZWebTask *task = ...
[task beginTaskWithCallbackBlock:^{
[self hideProgressIndicator];
}];
}
This example calls a method to display the progress indicator, then creates the task and tells it to start. The callback block specifies the code to be executed once the task completes; in this case, it simply calls a method to hide the progress indicator. Note that this callback block captures self in order to be able to call the hideProgressIndicator method when invoked. It’s important to take care when capturing self because it’s easy to create a strong reference cycle, as described later in Avoid Strong Reference Cycles when Capturing self.
In terms of code readability, the block makes it easy to see in one place exactly what will happen before and after the task completes, avoiding the need to trace through delegate methods to find out what’s going to happen.
The declaration for the beginTaskWithCallbackBlock: method shown in this example would look like this:
- (void)beginTaskWithCallbackBlock:(void (^)(void))callbackBlock;
The (void (^)(void)) specifies that the parameter is a block that doesn’t take any arguments or return any values. The implementation of the method can invoke the block in the usual way:
- (void)beginTaskWithCallbackBlock:(void (^)(void))callbackBlock {
...
callbackBlock();
}
Method parameters that expect a block with one or more arguments are specified in the same way as with a block variable:
- (void)doSomethingWithBlock:(void (^)(double, double))block {
...
block(21.0, 2.0);
}