一般问题
直到现在,我一直认为self->_ivar
等于_ivar
. 今天我发现这并不完全正确。
例如,请参见以下代码片段:
@interface TestClass : NSObject {
NSString *_testIVar;
}
@end
@implementation TestClass
- (instancetype)init
{
if ((self = [super init])) {
_testIVar = @"Testing Only";
}
return self;
}
- (void)test
{
{
NSInteger self = 42;
NSLog(@"without arrow: %@", _testIVar); /* OK */
NSLog(@"with arrow: %@", self->_testIVar); /* COMPILER ERROR! */
}
}
@end
即使我self
用一些NSInteger
也命名self
的东西隐藏了原件,隐含的 ivar 语法_testIVar
仍然可以找到“原始”自我,而self->_testIVar
显然没有。在后一种情况下,编译器正确地抱怨
成员引用类型“NSInteger”(又名“long”)不是指针
然而,在第一种情况下,它只是有效。
现实世界的问题
这个例子可能看起来相当人为,但它根本不是。例如,ExtObjC项目(由ReactiveCocoa使用)定义了非常方便的方法@weakify(var)
,它通过定义非常方便的语法(不再需要编写奇怪和繁琐的语法)@strongify(var)
来帮助防止在块中强捕获(和其他对象 )。例如:self
__weak typeof(self) weakSelf = self; [...] ^{ __strong typeof(self) strongSelf = weakSelf; [...] }
- (void)someMethod
{
@weakify(self);
dispatch_async(self.someQueue, ^{
@strongify(self);
NSLog(@"self @ %p", self);
}
}
如果没有@weakify
and @strongify
,该块将捕获对 的强引用self
。与它@weakify
并@strongify
没有。self
因此,在块运行之前,不会推迟释放。但是,主要优点是您不需要记住使用weakSelf
orstrongSelf
代替,self
因为“原始”self
是隐藏的。
这非常方便,ExtObjC通过使用宏生成类似于以下内容的@weakify
/来实现:@strongify
- (void)someMethod
{
__weak typeof(self) _weakSelf = self;
dispatch_async(self.someQueue, ^{
__strong typeof(self) self = _weakSelf;
NSLog(@"self @ %p", self);
}
}
很公平,这更好,因为我们可以继续使用self
而无需实际捕获对self
. 然而,只要我们使用implicit-ivars-of-self-syntax,对“原始”的强引用self
仍然会被捕获!
- (void)someMethod
{
@weakify(self);
dispatch_async(self.someQueue, ^{
@strongify(self); /* compiler warning: Unused variable self here!!! */
NSLog(@"self->_testIVar: %@", _testIVar);
}
}
杂项
在块中使用 ivars 时,我们肯定会捕获self
. 例如,请参阅此屏幕截图:
。
屏幕截图的另一个有趣之处是警告消息是
未使用的变量“自我”
在下面的行中
在此块中强烈捕获“自我”可能会导致保留周期
这就是为什么我认为有两个版本的self
:-)
问题
这里的实际问题是:到底是什么_testIVar
意思?它如何找到“原始”self
指针?
澄清(另见我的屏幕截图):正如@MartinR 指出的(这也是我的想法),有一些特殊版本self
无法更改,仅用于隐式自我ivar-access。这在某处有记录吗?基本上在哪里定义了隐式self
指的是什么?它的行为似乎与例如 Java 的行为相同 (with this
),但不同之处this
在于您无法覆盖的保留关键字。
问题也不是如何“修复”它,只是写self->_testIVar
将是我在@weakify
/@strongify
示例中想要的。我认为通过使用@weakify
/@strongify
你不能再犯隐式强捕获的错误,self
但事实似乎并非如此。