说我有这样的事情:
@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
,这还是不好吗?
答案 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个不错的选择。