Objective-C-代码块Block回顾
OC中的代码块是iOS4.0+ 和Mac OS X 10.6+ 引进的对C语言的扩展,用来实现匿名函数的特性。类似于其他语言脚本语言或者编程语言中的闭包或者是Lambda表达式,可能第一眼看上去很怪异,不过开发的过程中会越来越多的用到Block,还是了解多一点比较好。Block方面的内容也有很多,本文从实际使用的角度大概讲一下Block的基本概念和实践。
首先看一个苹果官网的例子:
int (^Multiply)(int, int) = ^(int num1, int num2) { return num1 * num2; }; int result = Multiply(7, 4); // Result is 28.
上面的代码定义了一个Block,类似于C#中的委托,int表示返回类型,^是关键标示符,(int,int)是参数类型,不过需要注意的,正常的方式是将返回类型用()包裹,这里是将Block的名称包裹,网上有一个类似的图片,大家可以参考一下:
Block除了能够定义参数列表、返回类型外,还能够获取被定义时的词法范围内的状态(将变量作为参数传递之后,可以修改之后返回).Block都是一些简短代码片段的封装,适用作工作单元,通常用来做并发任务、遍历、以及回调。下面看一个通知的例子:
- (void)viewDidLoad { [super viewDidLoad]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; } - (void)keyboardWillShow:(NSNotification *)notification { // Notification-handling code goes here. }
以上是调用addServer方法的例子,不过也可以这么写:
- (void)viewDidLoad { [super viewDidLoad]; [[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardWillShowNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { // Notification-handling code goes here. }]; }
苹果官网这个使用Block的例子如果第一次看可能不是那么好理解,如果仔细的看addServerName的定义发现:
- (id <NSObject>)addObserverForName:(NSString *)name object:(id)obj queue:(NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *note))block NS_AVAILABLE(10_6, 4_0);
其中Block参数定义的时候是这样的:
(void (^)(NSNotification *note))block NS_AVAILABLE(10_6, 4_0)
括号包裹起来的内容,第一个是返回值类型,之后的用用括号包裹^,之后的 话才是传递类型,基于以上的理解,可以这么写:
void(^MyBlock)(NSNotification *)=^(NSNotification *note){ note=nil; }; [[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardWillShowNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:MyBlock];
Block在苹果的API文档中随处看见其身影,常见的情况任务完成时回调处理,消息监听回调处理,错误回调处理,枚举回调,视图动画、变换,排序,比如说在NSDictionary中的方法中:
- (void)enumerateKeysAndObjectsWithOptions:(NSEnumerationOptions)opts usingBlock:(void (^)(id key, id obj, BOOL *stop))block NS_AVAILABLE(10_6, 4_0);
任务完成时候的调用:
- (IBAction)animateView:(id)sender { CGRect cacheFrame = self.imageView.frame; [UIView animateWithDuration:1.5 animations:^{ CGRect newFrame = self.imageView.frame; newFrame.origin.y = newFrame.origin.y + 150.0; self.imageView.frame = newFrame; self.imageView.alpha = 0.2; } completion:^ (BOOL finished) { if (finished) { // Revert image view to original. self.imageView.frame = cacheFrame; self.imageView.alpha = 1.0; } }]; }
通知机制中的处理:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { opQ = [[NSOperationQueue alloc] init]; [[NSNotificationCenter defaultCenter] addObserverForName:@"CustomOperationCompleted" object:nil queue:opQ usingBlock:^(NSNotification *notif) { NSNumber *theNum = [notif.userInfo objectForKey:@"NumberOfItemsProcessed"]; NSLog(@"Number of items processed: %i", [theNum intValue]); }]; }
枚举数组的时候的调用:
NSString *area = @"Europe"; NSArray *timeZoneNames = [NSTimeZone knownTimeZoneNames]; NSMutableArray *areaArray = [NSMutableArray arrayWithCapacity:1]; NSIndexSet *areaIndexes = [timeZoneNames indexesOfObjectsWithOptions:NSEnumerationConcurrent passingTest:^(id obj, NSUInteger idx, BOOL *stop) { NSString *tmpStr = (NSString *)obj; return [tmpStr hasPrefix:area]; }]; NSArray *tmpArray = [timeZoneNames objectsAtIndexes:areaIndexes]; [tmpArray enumerateObjectsWithOptions:NSEnumerationConcurrent|NSEnumerationReverse usingBlock:^(id obj, NSUInteger idx, BOOL *stop) { [areaArray addObject:[obj substringFromIndex:[area length]+1]]; }]; NSLog(@"Cities in %@ time zone:%@", area, areaArray);
也可以写一个Block在截取字符串,做一些自己需要的事情:
NSString *musician = @"Beatles"; NSString *musicDates = [NSString stringWithContentsOfFile: @"/usr/share/calendar/calendar.music" encoding:NSASCIIStringEncoding error:NULL]; [musicDates enumerateSubstringsInRange:NSMakeRange(0, [musicDates length]-1) options:NSStringEnumerationByLines usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) { NSRange found = [substring rangeOfString:musician]; if (found.location != NSNotFound) { NSLog(@"%@", substring); } }];
视图动画和转换中的实践:
[UIView animateWithDuration:0.2 animations:^{ view.alpha = 0.0; } completion:^(BOOL finished){ [view removeFromSuperview]; }];
两个视图之间的动画:
[UIView transitionWithView:containerView duration:0.2 options:UIViewAnimationOptionTransitionFlipFromLeft animations:^{ [fromView removeFromSuperview]; [containerView addSubview:toView] } completion:NULL];
数组排序的实践:
NSArray *stringsArray = [NSArray arrayWithObjects: @"string 1", @"String 21", @"string 12", @"String 11", @"String 02", nil]; static NSStringCompareOptions comparisonOptions = NSCaseInsensitiveSearch | NSNumericSearch | NSWidthInsensitiveSearch | NSForcedOrderingSearch; NSLocale *currentLocale = [NSLocale currentLocale]; NSComparator finderSort = ^(id string1, id string2) { NSRange string1Range = NSMakeRange(0, [string1 length]); return [string1 compare:string2 options:comparisonOptions range:string1Range locale:currentLocale]; }; NSLog(@"finderSort: %@", [stringsArray sortedArrayUsingComparator:finderSort]);
当然关于Block究竟是如何实现的,内存中是如何定义,如何保存的可以参考:http://blog.csdn.net/jasonblog/article/details/7756763
参考资料:https://developer.apple.com/library/ios/featuredarticles/Short_Practical_Guide_Blocks/
出处:http://www.cnblogs.com/xiaofeixiang
说明:博客经个人辛苦努力所得,如有转载会特别申明,博客不求技惊四座,但求与有缘人分享个人学习知识,生活学习提高之用,博客所有权归本人和博客园所有,如有转载请在显著位置给出博文链接和作者姓名,否则本人将付诸法律。