zoukankan      html  css  js  c++  java
  • 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/

  • 相关阅读:
    我为何需要使用空接口?
    Castle 整合.NET Remoting
    MVC结构简介
    在asp.net页面上得到Castle容器的实例
    Castle.MVC框架介绍
    08.vue-router动态路由匹配
    07. vue-router嵌套路由
    06.路由重定向
    04 Vue Router路由管理器
    ES6新特性之 let 、const
  • 原文地址:https://www.cnblogs.com/xiaofeixiang/p/4254879.html
Copyright © 2011-2022 走看看