Blocks Programming Topics

Blocks Programming Topics


介绍

    Block对象是一个c语言级别的语法和运行时特性,它和标准的C函数有相似之处,但是它除了可执行的代码之外还包含了变量。变量既可以是自动内存管理的(栈区)也可以是手动内存管理的(堆区)。因此Block可以维持一组数据用来影响行为。

    你可以使用blocks组成函数表达式从而传递给API接口,并且可以可选存储和多线程。Blocks用作回调函数尤为有用,因为block拥有着所有的可执行代码和在执行区间用到的变量数据。

    Blocks在GCC编译器中也是可用的,你可以在OS X 10.6之后或者iOS 4.0 或更高版本上使用。Blocks的运行时系统是开源的你可以在LLVM’s compiler-rt subproject repository处找到

    你需要读一读本文档看看block到底是什么和block到底怎样和C C++ Objective-C使用。


     开始使用Blocks


    下面的部分使用练习的例子帮助你学会blocks

   

声明和使用一个代码块Block

你可以使用^运算符声明一个block变量并且标识着一个block的开始,block的代码块在{}之间,例子如下int 

multiplier = 7;
int (^myBlock)(int) = ^(int num) {
    return num * multiplier;
};


    注意block中可以使用在同一作用域中定义的变量。

    如果你把block定义为一个变量,你可以在稍后像用函数一样使用它。

  int multiplier = 7;
  int (^myBlock)(int) = ^(int num) {
    return num * multiplier;
  };
  printf("%d", myBlock(3));
  // prints "21"


 直接使用Block

很多情况,你可能不希望声明一个Block变量。而是仅仅在作为函数的block处内联实现。下面的例子就是使用block作为最后一个参数。

char *myCharacters[3] = { "TomJohn", "George", "Charles Condomine" };
qsort_b(myCharacters, 3, sizeof(char *), ^(const void *l, const void *r) {
    char *left = *(char **)l;
    char *right = *(char **)r;
    return strncmp(left, right, 1);
});
// myCharacters is now { "Charles Condomine", "George", "TomJohn" }


 在Cocoa中使用Blocks


    Cocoa框架中有很多方法使用block作为一个参数,比较有代表性的就是执行一个对象集合上的操作,或者在一个操作完成后使用一个回调函数。下面的例子展示了在NSArray中的sortedArrayUsingComparator:方法上如何使用block。

这个方法有唯一的参数--block,为了说明,这种情况下block被定义为一个NSComparator的局部对象

NSArray *stringsArray = @[ @"string 1",
                             @"String 21",
                             @"string 12",
                             @"String 11",
                             @"String 02" ];
static NSStringCompareOptions comparisonOptions = NSCaseInsensitiveSearch |
  NSNumericSearch |
          NSWidthInsensitiveSearch | NSForcedOrderingSearch;
  NSLocale *currentLocale = [NSLocale currentLocale];
  NSComparator finderSortBlock = ^(id string1, id string2) {
      NSRange string1Range = NSMakeRange(0, [string1 length]);
      return [string1 compare:string2 options:comparisonOptions range:string1Range
  locale:currentLocale];
};
NSArray *finderSortArray = [stringsArray sortedArrayUsingComparator:finderSortBlock];NSLog(@"finderSortArray: %@", finderSortArray);
  /*
  Output:
  finderSortArray: (
      "string 1",
      "String 02",
      "String 11",
      "string 12",
      "String 21"
)*/ 


__block 变量

block一个强大的特性就是它可以修改同一作用域的变量。你可以用__block存储类型说明符标志一个变量是可修改地。为了迎合 “Blocks withCocoa"的例子,你可以用block变量计数有多少字符串是相等的。

为了说明,在这种情况下,直接使用局部变量在block中是只读的。

NSArray *stringsArray = @[ @"string 1",
@"String 21", // <-
@"string 12",
@"String 11",
@"Strîng 21", // <-
@"Striñg 21", // <-
@"String 02" ];
NSLocale *currentLocale = [NSLocale currentLocale];
__block NSUInteger orderedSameCount = 0;
NSArray *diacriticInsensitiveSortArray = [stringsArray
sortedArrayUsingComparator:^(id string1, id string2) {
    NSRange string1Range = NSMakeRange(0, [string1 length]);
    NSComparisonResult comparisonResult = [string1 compare:string2
options:NSDiacriticInsensitiveSearch range:string1Range locale:currentLocale];
    if (comparisonResult == NSOrderedSame) {
        orderedSameCount++;
}
    return comparisonResult;
}];
NSLog(@"diacriticInsensitiveSortArray: %@", diacriticInsensitiveSortArray);
NSLog(@"orderedSameCount: %d", orderedSameCount);
/*Output:
diacriticInsensitiveSortArray: (
    "String 02",
"string 1",
"String 11",
"string 12",
"String 21",
"Str\U00eeng 21",
      "Stri\U00f1g 21"
  )
  orderedSameCount: 2
  */


概念回顾

Block对象提供了一种方法可以让你创建一个hoc的函数体作为c或c派生语言(如:c++/ objective-c)的表达式。在其他的语言中,block对象有的叫做闭包(“closure”)。在这里他们被成为block,这样不会和标准c的属于混淆。


Block 功能 

block就是一个内联的代码集合:

  • 拥有一个像函数一样的参数列表
  • 可以有返回值
  • 可以使用在同一作用域中声明的变量
  • 可以可选的修改同一作用域的变量
  • 可以与其他定义在同一作用域的block共享修改变量
  • 在过了此作用域之后仍然可以修改此原先作用域的变量

你可以拷贝一个block甚至将它传递到其他线程中推迟执行(或者,在自己的线程中runloop)。编译器和运行时系统安排所有在block中引用的变量,在block的所有拷贝的生命周期中都会存储。尽管blocks在纯C/C++中也可以用,但是block也是一个objective-c对象。


使用

Block作为一个封装的工作单元,而且可能会并发执行,或者用作遍历集合,或者在一个其他的操作完成后作为一个回调函数。

Block作为替代传统回到函数的有用的选择,这里列举两个原因:

  1. They allow you to write code at the point of(正要) invocation(调用) that is executed later in the context of the methodimplementation(实现).

    Block因此作为库中很多方法的参数

  2. 他们允许你访问局部变量。

    Rather than using callbacks requiring a data structure that embodies all the contextual information youneed to perform an operation, you simply access local variables directly. 



声明和创建Blocks


声明一个block引用

Block变量保持引用到一个blocks。你可以声明他们使用的语法类似于函数指针,除了你要使用^来替代*之外。block类型完全可以喝其余的c语言基本类型交互,下面全是有效的block变量声明:

void (^blockReturningVoidWithVoidArgument)(void);
int (^blockReturningIntWithIntAndCharArguments)(int, char);
void (^arrayOfTenBlocksReturningVoidWithIntArgument[10])(int);

Blocks也支持可变的参数(...),如果一个block是无参数的,那么必须要在参数列表处指明void类型。

Blocks被设计为一种完全安全的类型,它通过给编译器一整套的元数据用来验证使用Blocks,参数传递到blocks,和blocks的返回值赋值。

 You can cast a block reference to apointer of arbitrary type and vice versa. You cannot, however, dereference a block reference via the pointerdereference operator (*)—thus a block's size cannot be computed at compile time. 


    你也可以自己创造一种Block的类型,这样你在多处使用Block将变得更简单

typedef float (^MyBlockType)(float, float);
MyBlockType myFirstBlock = // ... ;
MyBlockType mySecondBlock = // ... ;


创造一个Block

使用 ^运算符标识一个Block表达式的开始。它可能后面跟着一个空得参数列表。block的主体在{}之间。下面的例子定义了一个简单地BLock并且给它赋值--在这里Block以;结尾

float (^oneFrom)(float);
oneFrom = ^(float aFloat) {
    float result = aFloat - 1.0;
    return result;
};

如果你没有明确地定义一个block的表达式的返回值(就是以^开头的那个表达式),它会自动根据block的内容推测。如果你的参数列表是空的,那么你可以在block表达式(^开头的表达式)可以省略(void)。

如果block内部存在多个返回值,那么他们的类型必须匹配。



 全局Blocks

 若是文件级全局,你可以这样使用block

 

#import <stdio.h>
int GlobalInt = 0;
int (^getGlobalInt)(void) = ^{ return GlobalInt; };


 Blocks和变量


 这部分文章描述blocks和变量的交互,包括内存的管理


 

 变量的类型

 在block对象代码中,变量可能被分成5种:

 你可以使用3中标准的变量类型,就像在函数中一样:

  •  全局变量,包括静态局部变量
  •  全局函数
  •  局部变量和参数变量
 Blocks还支持两种变量类型:
  1. At function level are __blockvariables. These are mutable within the block (and the enclosing scope)and are preserved if any referencing block is copied to the heap.

  2. constimports. 

 最后,在一个方法的实现里,blocks可能使用Objective-C的实例变量。

  下面是用在Block里的变量的规则

  1.   全局变量是可访问的,包括局部静态变量
  2.   传递到block中的参数是可访问的(就像函数一样)
  3.   Stack (non-static) variables local to the enclosing lexical scope are captured as const variables. Their values are taken at the point of the block expression within the program. In nested blocks, the valueis captured from the nearest enclosing scope. 
  4. Variables local to the enclosing lexical scope declared with the __block storage modifier are providedby reference and so are mutable. 
  5. Local variables declared within the lexical scope of the block, which behave exactly like local variables ina function. 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值