Blocks Programming Topics

Getting Started with Blocks 

Declaring and Using a Block 

使用^操作符来声明一个block变量并且指明了block的开始。body在{}中如下的例子:

int multiplier = 7;

int (^myBlock)(int) = ^(int num) {

return num * multiplier;
};
};

例子解释如下:

你可以看到block body中可以访问 {}和自己是同一个scope的变量。

如果你将block声明为一个变量,那么你可以像函数一样使用它,例如:

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

//prints "21"

Using a Block Directly 

许多情况下你不需要声明block变量,而是简单写block inline作为参数。如下的例子使用qsort_b函数。qsort_b和标准的qsort_r函数很类似,但是将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" }

Blocks with Cocoa 

如下的例子展示的就是如何使用block和nsarray方法sortedArrayUsingComparator:这个方法有一个block的参数。为了说明,这里将block定义成了NSComparator local 变量。

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 Variables 

__block类型就说明了这个变量在block body中可以被改变。

  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",

"StrU00eeng 21",
      "StriU00f1g 21"
  )
  orderedSameCount: 2
  */

Conceptual Overview 

Block Functionality 

  • block 是一个匿名的code的inline collection
  • 有一个类似function的类型参数
  • 有一个返回类型
  • 可以捕获它定义范围内的状态
  • 可以有选择的改变定义范围内的状态
  • 可以在定义范围销毁后继续共享和改变定义状态

Usage 

blocks代表了小规模的,自容的代码片段。它们在执行并发的任务时作为封装单元尤其重要。block有别于传统callback函数的优点是:

1,它们允许你在方法执行后的某一个调用的地方书写代码

2,它们允许访问本地变量

Declaring and Creating Blocks 

Declaring a Block Reference 

void (^blockReturningVoidWithVoidArgument)(void);

int (^blockReturningIntWithIntAndCharArguments)(int, char);

void (^arrayOfTenBlocksReturningVoidWithIntArgument[10])(int);

没有返回类型的block必须显示表明为void类型

你也可以创建block类型当你在多个地方使用特定的signature

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

Creating a Block 

以下的例子定义了一个简单的block然后分配给了一个之前声明的变量oneFrom。

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

}; 

Global Blocks 

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

Blocks and Variables 

5中类型的变量

  • global variables, including static locals
  • global functions
  • local variables and parameters form an enclosing scope
  • __block varibales
  • const improts

Object and Block Variables 

Objective-C Objects 

当copy一个block时,它会创建一个object变量的强引用。如果你在一个执行方法中说使用block:

如果你通过引用来访问一个实例变量,就会产生self的强引用

如果你通过值来访问一个实例变量,就会产生这个变量的强引用

dispatch_async(queue, ^{
      // instanceVariable is used by reference, a strong reference is made to self
      doSomethingWithObject(instanceVariable);

});

  id localVariable = instanceVariable;
  dispatch_async(queue, ^{
      /*
        localVariable is used by value, a strong reference is made to localVariable
        (and not to self).

*/

      doSomethingWithObject(localVariable);
  });

Using Blocks 

Invoking a Block 

如果你将block声明为变量,你可以在函数中使用它,例如:

int (^oneFrom)(int) = ^(int anInt) {
    return anInt - 1;

};

printf("1 from 10 is %d", oneFrom(10));
// Prints "1 from 10 is 9"
float (^distanceTraveled)(float, float, float) =
                         ^(float startingSpeed, float acceleration, float time) {
    float distance = (startingSpeed * time) + (0.5 * acceleration * time * time);
    return distance;
};
float howFar = distanceTraveled(0.0, 9.8, 1.0);
// howFar = 4.9

Using a Block as a Function Argument 

你可以将block作为一个function参数进行传递。在大多数时候,你不需要声明blocks,只需要简单以内连形式来执行就可以了。以下的例子:

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);
});
// Block implementation ends at "}"
// myCharacters is now { "Charles Condomine", "George", "TomJohn" }

下面的例子展示了如何在dispatch_apply函数中使用block。
void dispatch_apply(size_t iterations, dispatch_queue_t queue, void
(^block)(size_t));

函数提交一个block到dispatch queue中。有三个参数。

#include <dispatch/dispatch.h>
size_t count = 10;

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_apply(count, queue, ^(size_t i) {
    printf("%u
", i);

}); 

###################################################

void func(void (^)(void));

int main(int argc, const char * argv[]) {

    @autoreleasepool {

        void (^hw)(void) = ^{NSLog(@"hellow world!");};

        func(hw);

    }

    return 0;

}

void func(void (^b) (void))

{

    NSLog(@"going to invoke the passed in block now.");

    b();

}

最后打印的结果为:

2015-01-07 14:41:38.296 FunWithBlocks[539:69766] going to invoke the passed in block now.

2015-01-07 14:41:38.298 FunWithBlocks[539:69766] hellow world!

Using a Block as a Method Argument 

cocoa提供了一系列使用blocks的方法。你传递block作为方法参数。例子:

NSArray *array = @[@"A", @"B", @"C", @"A", @"B", @"Z", @"G", @"are", @"Q"];
NSSet *filterSet = [NSSet setWithObjects: @"A", @"Z", @"Q", nil];
BOOL (^test)(id obj, NSUInteger idx, BOOL *stop);
test = ^(id obj, NSUInteger idx, BOOL *stop) {
    if (idx < 5) {
        if ([filterSet containsObject: obj]) {

return YES; }

}

return NO; };

NSIndexSet *indexes = [array indexesOfObjectsPassingTest:test];
NSLog(@"indexes: %@", indexes);

/* Output:

indexes: <NSIndexSet: 0x10236f0>[number of indexes: 2 (in 2 ranges), indexes: (0
3)]

*/ 

Copying Blocks 

其实你不需要copy一个block。只有当你想在scope destruction之后仍然想使用block的时候才会用到。copying将block移动到heap中。

Block_copy();
Block_release();

Debugging 

你可以在blocks中设置断点和单步跟踪。

You can set breakpoints and single step into blocks. You can invoke a block from within a GDB session using invoke-block, as illustrated in this example:

If you want to pass in a C string, you must quote it. For example, to pass this string into the doSomethingWithString block, you would write the following:

page23image9664 page23image9824 page23image9984 page23image10144
$ invoke-block myBlock 10 20page23image10912page23image11072page23image11232page23image11392
$ invoke-block doSomethingWithString ""this string""
原文地址:https://www.cnblogs.com/lisa090818/p/4207922.html