块可以通过多种方式帮助您编写更好的代码。这里有两个。
更可靠的代码
一个优点是代码更可靠。这是一个具体的例子。
在 iOS 4.0 之前,要为视图设置动画,您必须使用 beginAnimations:context: 和 commitAnimations 消息,like this:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationDelay:1.0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
self.basketTop.frame = basketTopFrame;
self.basketBottom.frame = basketBottomFrame;
[UIView commitAnimations];
请注意,您必须记得拨打commitAnimations,否则您的应用会出现异常。编译器不会警告您忘记调用commitAnimations。
在 iOS 4.0 中,Apple 添加了块,并添加了使用块为视图设置动画的新方法。例如:
[UIView animateWithDuration:0.5 delay:1 options:UIViewAnimationOptionCurveEaseOut animations:^{
self.basketTop.frame = basketTopFrame;
self.basketBottom.frame = basketBottomFrame;
} completion:nil];
这里的优点是不会忘记提交动画。如果您忘记将} 放在块的末尾或将] 放在方法的末尾,编译器会给您一个语法错误。 Xcode 会自动补全消息名称,因此您不必记住它的拼写方式。
更好的代码组织
另一个优势是更好的代码组织。这是一个例子。
假设您想将UIImage 发送到服务器。将图像转换为 PNG 数据可能需要一些时间,因此您不想在执行此操作时阻塞主线程。您想在后台,在另一个线程上执行此操作。在 iOS 4.0 之前,您可能会决定使用NSOperationQueue。首先,您需要创建一个NSOperation 的子类来完成这项工作1:
@interface SendImageToServerOperation : NSOperation
@property (nonatomic, retain) UIImage *image;
@property (nonatomic, retain) NSURL *serverURL;
@end
@implementation SendImageToServerOperation
- (void)main {
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:self.serverURL];
request.HTTPBody =UIImagePNGRepresentation(self.image);
NSURLResponse *response;
NSError *error;
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
// Handle response/error here?
}
@end
然后,要真正做到这一点,您需要创建一个操作并将其放入队列中:
- (void)sendImage:(UIImage *)image toServerURL:(NSURL *)serverURL {
SendImageToServerOperation *operation = [SendImageToServerOperation new];
operation.image = image;
operation.serverURL = serverURL;
[backgroundQueue addOperation:operation];
}
代码散开。从 iOS 4.0 开始,您可以使用块(以及新的 GCD 框架2)将它们组合在一起:
- (void)sendImage:(UIImage *)image toServerURL:(NSURL *)serverURL {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:serverURL];
request.HTTPBody =UIImagePNGRepresentation(image);
NSURLResponse *response;
NSError *error;
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
// Handle response/error here?
});
}
您不必创建一个新类甚至一个单独的函数。您甚至不必创建任何额外的对象。您可以将代码放在最容易理解和维护的地方。
脚注 1. 这不一定是将数据上传到服务器的最佳方式。出于教育目的,我选择了一种简单的方法。但是,希望在后台线程上创建 PNG 数据是现实的。
脚注 2。NSBlockOperation 类(从 iOS 4.0 开始)允许您直接使用块与 NSOperationQueue,如果您更喜欢 GCD。