编程范式有三种:过程式编程、面向对象编程和函数式编程。大部分现代编程语言并不能单纯地归为某一范式。这些语言常常看起来属于某种范式,同时又兼具其他范式的特色。Objective-C主要是面向对象的,同时又通过块借鉴了一些函数式的特性。
函数式编程(Functional Programming,FP)
块:可以把块作为参数传递,“复制”以备稍后使用,也可以对其执行几乎所有通常会用在基本数据类型上的操作。C程序员是用函数指针做这件事的。而块区别于指针的一点是:块可以在其他方法的词法作用域中声明,而且可以在这个作用域中“捕获变量的状态”,不需要程序员做任何事块就有上下文信息。
例子:展示一个UIAlertView,当用户按下确认按钮时执行一个动作。
过程式方法:先创建一个UIAlertView对象,设置委托并实现回调,显示UIAlertView,然后释放。
- (IBAction) buttonTapped:(id) sender
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"send email"
message:@"Are you sure you want to send is now?"
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"send",nil];
[alert show];
[alert release];;
}
-(void) alertView:(UIAlertView*) alertView didDismissWithButtonIndex:(NSInteger) buttonIndex
{
if(buttonIndex != [alertView cancelButtonIndex])
{
[self sendTheMail];
}
}
-(void) sendTheMail
{
//发送邮件的代码
}
现在看看一个遵循函数式范式的UIAlertView的调用
[UIAlertView showAlertViewWithTitle:@"Send email"
message:@"Are you sure you want to send it now?"
cancelButtonTitle:@"Cancel"
otherButtonTitles:[NSArray arrayWithObjects:@"send",nil]
onCompletion:^{
//发送邮件的代码
}
onCancel:^{//其他处理
}
];
函数式范式不需要实现委托,不需要分配和释放对象,不需要明确地显示警告对话框。
块是一种比较特殊的Objective-C对象。跟传统的对象不同的是,块不是在堆上创建的。主要有两个原因,一是在栈上分配空间几乎总是比在堆上快;二是出于访问其他局部变量的需要。当块作为参数传递给别的方法时,块被复制,它会从栈移动到堆上。这就意味着默认情况下块不能修改上下文数据。但是也可以修改局部变量,只是需要用__block来修饰声明变量。这个修饰符是为了命令编译器当块被复制时也把变量__block复制过去。
知道了块的原理,现在就来实现块。
(1)为UIAlertView 添加类别,头函数为UIAlertView+Blocks.h
#import <Foundation/Foundation.h>
//用typedef定义DismissBlock和CancelBlock
typedef void (^DismissBlock)(int buttonIndex);
typedef void (^CancelBlock)();
@interface UIAlertView (Blocks) <UIAlertViewDelegate>
//方法定义
+ (UIAlertView*) showAlertViewWithTitle:(NSString*) title
message:(NSString*) message
cancelButtonTitle:(NSString*) cancelButtonTitle
otherButtonTitles:(NSArray*) otherButtons
onDismiss:(DismissBlock) dismissed
onCancel:(CancelBlock) cancelled;
@end
(2)实现UIAlertView+Blocks.m
#import "UIAlertView+Blocks.h"
//为块声明静态存储空间
static DismissBlock _dismissBlock;
static CancelBlock _cancelBlock;
@implementation UIAlertView (Blocks)
//实现基于块的方法
+ (UIAlertView*) showAlertViewWithTitle:(NSString*) title
message:(NSString*) message
cancelButtonTitle:(NSString*) cancelButtonTitle
otherButtonTitles:(NSArray*) otherButtons
onDismiss:(DismissBlock) dismissed
onCancel:(CancelBlock) cancelled {
_cancelBlock = [cancelled copy];
_dismissBlock = [dismissed copy];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title
message:message
delegate:[self self]
cancelButtonTitle:cancelButtonTitle
otherButtonTitles:nil];
for(NSString *buttonTitle in otherButtons)
[alert addButtonWithTitle:buttonTitle];
[alert show];
return alert;
}
//处理UIAlertViewDelegate
+ (void)alertView:(UIAlertView*) alertView didDismissWithButtonIndex:(NSInteger) buttonIndex {
if(buttonIndex == [alertView cancelButtonIndex])
{
_cancelBlock();
}
else
{
_dismissBlock(buttonIndex - 1); // cancel button is button 0
}
}
@end
(3)调用
[UIAlertView showAlertViewWithTitle:@"Test"
message:@"Hi there"
cancelButtonTitle:@"Dismiss"
otherButtonTitles:[NSArray arrayWithObject:@"OK"]
onDismiss:^(int buttonIndex) {
NSLog(@"Button Dismissed");
}
onCancel:^ {}];
这个就跟Android中的回到函数类似了
本文介绍如何在Objective-C中利用块(Block)实现函数式编程风格。通过对比过程式方法和函数式方法调用UIAlertView的例子,展示了块如何简化代码并提供更简洁的编程体验。
2031

被折叠的 条评论
为什么被折叠?



