【问题标题】:Why doesn't accessing self's property raise compiler warning in block owned by self为什么访问 self 的属性不会在 self 拥有的块中引发编译器警告
【发布时间】:2013-02-12 07:52:34
【问题描述】:

我对内存管理/保留周期有点困惑。这是一个简单的类:

@interface Test : NSObject {
    NSObject *objectA;
}
@property (nonatomic, strong) NSObject *objectB;

- (void)methodA;
@end

假设我有一个 Test 实例拥有的块。在这块我做:

    objectA = nil;

我得到一个编译器,说它正在这个块中捕获自我,这将导致保留周期。为什么?我在这里看不到自己。

如果我这样做:

self.objectB = nil;

没有警告!如果有的话,我应该在这里收到警告。

如果我这样做:

[self methodA];

我在这里得到一个警告。所以我不确定幕后到底发生了什么。我希望第一个不给我警告,最后两个给我一个警告(因为我保留了一个指向自我的强指针),但实际上恰恰相反。

这是一个例子:

@interface ListVC () {
    NSObject *objectA;
}
@property (nonatomic, strong) NSObject *objectB;
- (void)methodA;
@end

在 viewDidLoad 中:

- (void)viewDidLoad {
    [super viewDidLoad];

    [self.tableView addPullToRefreshWithActionHandler:^{
        self.objectB = nil; //no warning here
        objectA = nil; //warning here
        [self methodA]; //warning here (if i place this above previous warning
    }];
}

【问题讨论】:

  • 你的 .h 是这样的吗? @interface Test () 因为它看起来像一个类别。
  • @JackyBoy 这只是我快速编写的一个示例。我没有 .h 或 .m,我在 SO 编辑器上写道。
  • 好吧,我们需要检查所有内容以查看问题所在。我刚刚尝试了我的代码,在一个块内将 ivar 设置为 nil,一切都按预期进行。没有警告。有代码示例吗?
  • 第一个(与任何 ivar 访问一样)隐式为 self->objectB; 在这种情况下,块保留 self,而不是 ivar 中的对象。为什么第二个没有警告我不知道;它应该,因为它相当于第三个。
  • @JackyBoy 检查更新示例

标签: ios objective-c cocoa-touch


【解决方案1】:

在我看来,编译器只是不想为同一个块多次警告您。我不确定这是否算作一项功能,但我看不出还有什么可能发生。

假设我们使用相同的编译器版本(我的是 Apple LLVM 4.2),试试这个:

@interface Jubilee : NSObject

@property (copy, nonatomic) NSData * d;

@end

@implementation Jubilee
{
    NSString * s;
    dispatch_block_t block;
}

@synthesize d;

- (void)erase
{
    block = ^{
        s = @"Agamemnon";
    };

    block = ^{
        self.d = [NSData data];
    };

    block = ^{
        [self prevaricate];
    };

}

- (void)assemble
{
    block = ^{
        s = @"Agamemnon";
        self.d = [NSData data];
        [self prevaricate];
    };
}

- (void)prevaricate
{
}

@end

我在erase 中的每个块处都收到警告,但仅针对assemble 中块的第一行。警告在这些行中的任何一行都是正确的。当您对 ivar 进行裸引用时,它隐式为 self->ivar;,并且 Block 将保留 self 而不是 ivar 中的对象。

【讨论】:

  • 酷,感谢您的详细回复。另外,我发现有时,即使是块的第一行也不会触发警告。例如,如果您执行 my_dictionary[@"hello"] = @"hi",即使它是第一行...也不会生成警告。 :( - 我猜这与使用字典上的 [] 访问器有关
【解决方案2】:

第一个警告是正确的。访问块内的实例变量将隐式保留 self。 您没有收到第二条语句的警告这一事实几乎看起来像是一个编译器错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-12
    • 2019-01-14
    • 1970-01-01
    • 2012-06-08
    • 2010-11-09
    • 2017-03-04
    • 2023-03-19
    • 2020-01-24
    相关资源
    最近更新 更多