IOS block编程指南 5 Block和变量

Blocks and Variables(Block和变量)

This article describes the interaction between blocks and variables, including memory management.

本文讲述了block和变量之间的内在关系,包括内存管理。

Types of Variable(变量类型)

Within the block object’s body of code, variables may be treated in five different ways.

You can reference three standard types of variable, just as you would from a function:

  • Global variables, including static locals

  • Global functions (which aren’t technically variables)

  • Local variables and parameters from an enclosing scope

block对象中的代码中,变量会被五种方法区别对待。
你可以参考三种标准变量,就像你在一个函数中那样:
  • 全局变量,包括静态的本地变量
  • 全局函数,(这个并不是技术上的变量)
  • 本地变量,和同一个作用域的参数

Blocks also support two other types of variable:

  1. At function level are __block variables. These are mutable within the block (and the enclosing scope) and are preserved if any referencing block is copied to the heap.

  2. const imports.

Finally, within a method implementation, blocks may reference Objective-C instance variables—see Object and Block Variables.

block也支持其他两种类型的变量
  1. 在函数级别的_block 变量。这些变量在block中是可变的,同时如果引用变量的block拷贝进堆堆,手动管理内存)内存就会保存 。 
  2. 常量
最后,随着方法的实现,blocks会引用objective-C的实例变量——参见:   Object and Block Variables

The following rules apply to variables used within a block:

  1. Global variables are accessible, including static variables that exist within the enclosing lexical scope.

  2. Parameters passed to the block are accessible (just like parameters to a function).

  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 value is captured from the nearest enclosing scope.

  4. Variables local to the enclosing lexical scope declared with the __block storage modifier are provided by reference and so are mutable.

    Any changes are reflected in the enclosing lexical scope, including any other blocks defined within the same enclosing lexical scope. These are discussed in more detail inThe __block Storage Type.

  5. Local variables declared within the lexical scope of the block, which behave exactly like local variables in a function.

    Each invocation of the block provides a new copy of that variable. These variables can in turn be used as const or by-reference variables in blocks enclosed within the block.

以下规则适用于block中使用的变量:
  1. 全局变量可以访问,包括作用域内的静态变量。(这里block有对全局变量的读写权限)
  2. 传入block中的参数可以访问(就像函数中的参数)。
  3. 作用域中的栈(自动内存管理)(非静态)变量,被当做常量来使用。  在程序中他们的值被block表达式调用。在嵌套block中,会使用最近的作用域中的变量。(笔者的理解是,嵌套的只能用最近的。PS:这一大段其实就几个字:block中普通变量是只读的)
  4. 作用域中的_block变量提供的是引用,所以是可变的。   所有的变动都会反映在作用域中,包括同一个作用域内定义了其他的block。更具体的讨论:见The __block Storage Type
  5. block中声明的局部变量,他们的行为很像函数中的局部变量。  block的每次调用都会给变量提供一份新的拷贝。这些在block作用域中的变量可以是常量,也可以做变量(引用的)。

The following example illustrates the use of local non-static variables:

下列例子说明了非静态局部变量变量的使用

int x = 123;
 
void (^printXAndY)(int) = ^(int y) {
 
    printf("%d %d\n", x, y);
};
 
printXAndY(456); // prints: 123 456

As noted, trying to assign a new value to x within the block would result in an error:

值得注意的是,试图在块内给block赋值会返回error

int x = 123;
 
void (^printXAndY)(int) = ^(int y) {
 
    x = x + y; // error
    printf("%d %d\n", x, y);
};

To allow a variable to be changed within a block, you use the __block storage type modifier—see The __block Storage Type.

为了允许在block中修改变量,你需要用 _block 类型存储 ,见: The __block Storage Type

The __block Storage Type(_block 存储类型)

You can specify that an imported variable be mutable—that is, read-write— by applying the __block storage type modifier. __block storage is similar to, but mutually exclusive of, the registerauto, and static storage types for local variables.

__block variables live in storage that is shared between the lexical scope of the variable and all blocks and block copies declared or created within the variable’s lexical scope. Thus, the storage will survive the destruction of the stack frame if any copies of the blocks declared within the frame survive beyond the end of the frame (for example, by being enqueued somewhere for later execution). Multiple blocks in a given lexical scope can simultaneously use a shared variable.

As an optimization, block storage starts out on the stack—just like blocks themselves do. If the block is copied using Block_copy (or in Objective-C when the block is sent a copy), variables are copied to the heap. Thus, the address of a __block variable can change over time.

There are two further restrictions on __block variables: they cannot be variable length arrays, and cannot be structures that contain C99 variable-length arrays.



你可以指定一个输入的变量是可变的,(可以读,写),通过使用_block存储类型修饰符。_block很类似,(但是区别于),局部变量的 register,auto,stack,存储类型。
_block变量生存的存储范围,是变量的作用域和所有block和block的拷贝声明的或者创造的作用域。因此呢,如果block的一个拷贝声明在一个没有被销毁的框架里面,存储会在栈内存销毁时不被销毁,直到这个框架结束(举例,被排到某处,延后执行)。同一作用域下的多个block可以共同使用一个变量。
作为优化,block存储从栈开始——就像block他们自己在做。如果block使用Block_copy(或Objective-C,当block发送出一份拷贝的时候),变量拷贝到堆(手动内存管理)。这样_block变量就可以随时改变地址了。
对于_block变量有两个更进一步的约束:他们不能作为变长数组,不能成为包含C99数组的结构。

The following example illustrates use of a __block variable:

下面的例子说说明了_block变量的使用。

__block int x = 123; //  x lives in block storage
 
void (^printXAndY)(int) = ^(int y) {
 
    x = x + y;
    printf("%d %d\n", x, y);
};
printXAndY(456); // prints: 579 456
// x is now 579

The following example shows the interaction of blocks with several types of variables:

这个例子展现了几种类型的block的相互作用

extern NSInteger CounterGlobal;
static NSInteger CounterStatic;
 
{
    NSInteger localCounter = 42;
    __block char localCharacter;
 
    void (^aBlock)(void) = ^(void) {
        ++CounterGlobal;
        ++CounterStatic;
        CounterGlobal = localCounter; // localCounter fixed at block creation
        localCharacter = 'a'; // sets localCharacter in enclosing scope
    };
 
    ++localCounter; // unseen by the block 
    localCharacter = 'b';
 
    aBlock(); // execute the block
    // localCharacter now 'a'
}

Object and Block Variables (对象和block变量)


Blocks provide support for Objective-C and C++ objects, and other blocks, as variables.

block可以作为变量,支持Objective-C和C++对象,其他block。

Objective-C Objects(Objective—C 对象)

When a block is copied, it creates strong references to object variables used within the block. If you use a block within the implementation of a method:

  • If you access an instance variable by reference, a strong reference is made to self;

  • If you access an instance variable by value, a strong reference is made to the variable.

当一个block被拷贝了,他创建一个对block中使用的对象变量的强引用。如果你在块内实现了一个方法:
  • 如果你通过引用访问一个实例变量,就对self建立一个强引用。
  • 如果你通过值访问了一个实例变量,就对变量建立一个强引用。

The following examples illustrate the two different situations:

下面的例子说明了不同的情况

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);
});

To override this behavior for a particular object variable, you can mark it with the __block storage type modifier.

通过重写一个特定对象变量,你可以使用_block存储类型修饰符来标记它。

C++ Objects (C++对象)

In general you can use C++ objects within a block. Within a member function, references to member variables and functions are via an implicitly imported this pointer and thus appear mutable. There are two considerations that apply if a block is copied:

  • If you have a __block storage class for what would have been a stack-based C++ object, then the usual copy constructor is used.

  • If you use any other C++ stack-based object from within a block, it must have a const copy constructor. The C++ object is then copied using that constructor.

通常情况下你可以在C++对象中使用block。在一个成员函数中,对成员变量和函数的引用通过一个隐晦的this指针实现,然后就出现了变数。如果一个block申请拷贝,这里有两种情况考虑:
  • 如果你有一个基于栈的C++对象,里面有_block存储类,这个时候使用通常构造函数。
  • 如果你在一个block中使用其他的基于栈的C++对象,就必须使用常拷贝构造函数。C++对象拷贝的时候会用那个构造函数。


本文原创 转载请注明出处:http://blog.csdn.net/zhenggaoxing/article/details/44416595



  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值