1

例子:

extern void _objc_autoreleasePoolPrint();

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

    @autoreleasepool {

        id __weak blk;

        {
            int a = 10;

            blk = ^(NSString *msg){
                NSLog(@"msg: %@", msg);
                NSLog(@"%d", a);
            };
        }

        NSLog(@"blk: %@", blk);

        _objc_autoreleasePoolPrint();

        ((void (^)(NSString *))blk)(@"Hello!");

    }

    return 0;
}

输出是:

2013-05-18 13:24:10.355 __iOS_SimpleConsoleApplication[63449:c07] blk: (null)
objc[63449]: ##############
objc[63449]: AUTORELEASE POOLS for thread 0xac583a28
objc[63449]: 1 releases pending.
objc[63449]: [0x7a73000]  ................  PAGE  (hot) (cold)
objc[63449]: [0x7a73028]  ################  POOL 0x7a73028
objc[63449]: ##############

和崩溃:)

将块分配给 __weak blk 变量后,它在 autoreleasepool 中注册,因此在离开范围后它不应该等于 nil,但确实如此!为什么?

从 blk 捕获的变量“a”中删除后,我有以下输出:

2013-05-18 13:25:34.132 __iOS_SimpleConsoleApplication[63486:c07] blk: <__NSGlobalBlock__: 0x35d0>
objc[63486]: ##############
objc[63486]: AUTORELEASE POOLS for thread 0xac583a28
objc[63486]: 2 releases pending.
objc[63486]: [0x7923000]  ................  PAGE  (hot) (cold)
objc[63486]: [0x7923028]  ################  POOL 0x7923028
objc[63486]: [0x792302c]            0x35d0  __NSGlobalBlock__
objc[63486]: ##############
2013-05-18 13:25:34.142 __iOS_SimpleConsoleApplication[63486:c07] msg: Hello!

没有任何崩溃。

4

1 回答 1

3

知道了!

使用没有捕获变量的块,它被添加到 _NSGlobalBlock 内存段,因此它的内存地址始终有效,但是当块捕获变量“a”时,它被添加到 _NSStackBlock 内存段并在离开范围后被释放。

要使用捕获的变量,我们应该使用复制方法,该块将被移动到 _NSMallocBlock 内存段。

extern void _objc_autoreleasePoolPrint();

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

    @autoreleasepool {

        id blk;

        {
            int a = 10;

            blk = [^(NSString *msg){
                NSLog(@"msg: %@", msg);
                NSLog(@"a: %d", a);
            } copy];

        }

        NSLog(@"blk: %@", blk);

        _objc_autoreleasePoolPrint();

        ((void (^)(NSString *))blk)(@"Hello!");

    }

    return 0;
}

输出:

2013-05-18 13:43:51.947 __iOS_SimpleConsoleApplication[63822:c07] blk: <__NSMallocBlock__: 0x7190120>
objc[63822]: ##############
objc[63822]: AUTORELEASE POOLS for thread 0xac583a28
objc[63822]: 1 releases pending.
objc[63822]: [0x7b9f000]  ................  PAGE  (hot) (cold)
objc[63822]: [0x7b9f028]  ################  POOL 0x7b9f028
objc[63822]: ##############
2013-05-18 13:43:51.952 __iOS_SimpleConsoleApplication[63822:c07] msg: Hello!
2013-05-18 13:43:51.952 __iOS_SimpleConsoleApplication[63822:c07] a: 10
于 2013-05-18T09:49:18.937 回答