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

mic*_*den 3 memory objective-c 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
Run Code Online (Sandbox Code Playgroud)

问题出在这一行: 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;
    }
}];
Run Code Online (Sandbox Code Playgroud)

但是,如果我们没有明确地写self.name,那么这仍然是坏的,但写_name吗?

das*_*ght 5

是否_name就像使用坏self.name

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

你可以通过使用__weak Foo *weakSelf = self然后weakSelf在块中引用来解决它.

你可以参考这里使用相同的技巧 weakSelf->_name

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

  • @doctordoder:但应该注意`enumerateObjectsUsingBlock:`根本不会导致保留周期.您可以在块内部使用`self.name`或`_name`而不会出现问题.该块暂时保留自身,并在枚举完成后释放它.这里根本不需要弱引用. (4认同)