块中引用的实例变量和临时变量之间的区别是什么?

时间:2015-11-20 07:59:18

标签: objective-c objective-c-blocks

demo screenshot

就像屏幕截图所描述的那样。

//
//  ViewController.m
//  Test
//
//  Created by jam on 15/11/4.
//  Copyright © 2015年 Baidu Inc. All rights reserved.
//

#import "ViewController.h"
#import "CJTestObject.h"

@interface ViewController ()

@property (strong, nonatomic) CJTestObject *testObject1;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    _testObject1 = [[CJTestObject alloc] init];
    CJTestObject *testObject2 = [[CJTestObject alloc] init];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"_testObject1: %@", _testObject1);
        NSLog(@"testObject2: %@", testObject2);
    });
    _testObject1 = nil;
    testObject2 = nil;
}
@end

控制台输出

2015-11-20 18:07:28.855 Test[33585:417965] _testObject1: (null)
2015-11-20 18:07:28.857 Test[33585:417965] testObject2: <CJTestObject: 0x79f564f0>

我的问题是这两种变量在块中引用的不同之处。

1 个答案:

答案 0 :(得分:2)

在你的情况下,你有这两个对象类型的变量,所以你的块应该保留在你的情况下。

但这里的主要区别是testObject2(在方法范围中声明的变量)将被保留,但是当您在块中捕获_testObject1时,它会保留self而不是{ {1}}(在您的示例中)。 在块中捕获实例变量会导致保留_testObject1,因此当此块存在时,block将保留对self的强引用。

复制块时,它们引用的任何本地对象变量都会自动保留。然后在块被破坏时自动释放它们。这样可以确保引用保持有效。对self的任何引用都是对本地对象变量的引用,导致self被保留。对实例变量的任何引用都是对self的隐式引用,并导致同样的事情。

您可以在这个精彩的博客中找到更多详情

https://mikeash.com/pyblog/friday-qa-2009-08-14-practical-blocks.html

更新: 至于你的控制台输出,当块执行时会发生什么:

self

这里需要复制对NSLog(@"testObject1: %@", _testObject1); 的引用,并在执行时取消引用它的_testObject1实例变量&#34;指针&#34;。在C中它看起来像self。 您将_testObject1的引用设置为nil,在2秒后,您的块会查看此更新的&#39;参考

self->_testObject1

这里你的块复制并保留了对testObject2的引用。设置testObject2 = nil时,将变量的引用设置为nil。但是阻止仍然复制了#39;并保留地址到您的变量,因此它存储并打印该值。

看起来有点复杂但我希望能理解我的答案:)