Objective-C块寿命ARC [英] Objective-c block lifetime ARC

查看:100
本文介绍了Objective-C块寿命ARC的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对ARC下一个块的生存期感到困惑.我已经编写了一个单元测试来演示让我感到困惑的地方.

I'm confused about the lifetime of a block under ARC. I've written a unit test to demonstrate what is confusing me.

- (void)testBlock {
    NSObject *testObject = [[NSObject alloc] init];
    CompletionBlock testBlock = ^{ NSLog(@"%@", testObject); };
    XCTAssertNotNil(testObject, @"testObject should not be nil");

    __weak NSObject *weakTestObject = testObject;
    @autoreleasepool {
        testObject = nil;
    }
    XCTAssertNotNil(weakTestObject, @"testObject should be retained by testBlock");

    @autoreleasepool {
        testBlock = nil;
    }
    //THIS IS THE FAILING TEST CASE
    XCTAssertNil(weakTestObject, @"testObject should have been released when testBlock was released");
}

我猜测这种行为与块在堆栈/堆中的存储方式有关.

I'm guessing that this behavior has something to do with how blocks are stored on the stack/heap.

更新!

将块设置为nil不会像我期望的那样释放该块,因为它在堆栈中,并且直到它超出范围才被释放.强制块超出范围可修复我的测试.下面更新了代码.

Setting the block to nil doesn't release the block as I expected because it is on the stack and will not be released until it goes out of scope. Forcing the block to go out of scope fixes my test. Updated code below.

- (void)testBlock {
    NSObject *testObject = [[NSObject alloc] init];
    __weak NSObject *weakTestObject = testObject;

    @autoreleasepool {
        CompletionBlock testBlock = ^{ NSLog(@"%@", testObject); };
        XCTAssertNotNil(testBlock, @"testBlock should not be nil");
        XCTAssertNotNil(testObject, @"testObject should not be nil");

        testObject = nil;
        XCTAssertNotNil(weakTestObject, @"testObject should be retained by testBlock");
        //testBlock goes out of scope here
    }
    XCTAssertNil(weakTestObject, @"testObject should have been released when testBlock was released");
}

推荐答案

块是在堆栈上创建的,并且只有在范围退出时才被破坏,这非常类似于具有析构函数的C ++堆栈分配对象.这些块免于引用计数,并且将忽略 retain/release消息.仅在复制后(通过Block_copy()函数或copy消息),它们才成为可以保留和释放的普通堆分配对象.

Blocks are created on stack, and only become destroyed when scope exits, pretty much like C++ stack-allocated objects with destructors. These blocks are exempt from reference counting and will ignore retain/release messages. Only after being copied (via Block_copy() function or copy message) they become normal heap-allocated objects that can be retained and released.

在您的示例中,如果将所有代码包装在大括号中,则断言将开始工作.{ },以便断言在块变量的作用域结束后执行.

In your example, the assert shall start working if you wrap all the code before it in extra curly brackets { }, so that the assert executes after block variable's scope ends.

这篇关于Objective-C块寿命ARC的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆