可以在块中使用下划线表示自动合成属性(强引用周期)

时间:2014-06-29 18:39:54

标签: objective-c memory objective-c-blocks

说我有这样的事情:

@interface Foo : UIViewController

@property (nonatomic, strong) NSString *name;

@end

@implementation Foo

- (void)viewDidLoad
{
    [super viewDidLoad];
    _name = @"Me";
    NSArray *blackList = @[@"John", @"Malcolm", @"Jimmy"];
    [blackList enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        if ([obj isEqualToString:_name])  // Is _name just as bad as using self.name?
        {
            NSLog(@"You're on the blacklist!");
            *stop = YES;
        }
    }];
}

@end

问题出在这一行:if ([obj isEqualToString:_name])

我知道在块中引用self是不好的,你可以使用__weak Foo *weakSelf = self来解决它,然后在块中引用weakSelf

__weak Foo *weakSelf = self;
[blackList enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    if ([obj isEqualToString:weakSelf.name])
    {
        NSLog(@"You're on the blacklist!");
        *stop = YES;
    }
}];

但是,如果我们没有明确写self.name,而是写_name,这还是不好吗?

2 个答案:

答案 0 :(得分:5)

  

_name与使用self.name一样糟糕吗?

是的,确实如此。实际上,self引用仍然存在 - 编译器会为您插入它。

  

您可以使用__weak Foo *weakSelf = self绕过它,然后在块中引用weakSelf

您可以参考weakSelf->_name

在此处使用相同的技巧

注意:没有必要在enumerateObjectsUsingBlock:中使用此技巧,因为枚举完成并且块在方法范围内释放。只有当您将块放在self对象的变量中时,才会发生保留周期的威胁,同时还会从块中引用self

答案 1 :(得分:1)

如果我能正确理解这个问题,这里有两个不错的选择。

如您所示,创建weakSelf,并通过以下两种方式之一引用名称:

weakSelf.name

weakSelf->_name

或者只是创建一个对name的弱引用,并参考:

__weak __block NSString* weakName = name;

参考weakName

使用_name在技术上并不像self.name那么糟糕,因为你只会保留循环字符串对象而不是整个类,但是你&# 39;仍然在创建一个保留周期,你真的不应该这样做。

我已经得到纠正,显然self仍然留在这里,所以它与捕获self一样糟糕(它完全相同)。不过,这里仍有3个不错的选择。