Joh*_*iss 20 block objective-c ivar reactive-cocoa
直到现在,我一直认为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
Run Code Online (Sandbox Code Playgroud)
即使我隐藏了原始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);
}
}
Run Code Online (Sandbox Code Playgroud)
没有@weakify和@strongify,该块将捕获一个强引用self.随着@weakify而@strongify它却没有.因此,self在块运行之前,不会推迟释放.但主要的优点是你不需要记住使用weakSelf或strongSelf代替,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);
}
}
Run Code Online (Sandbox Code Playgroud)
很公平,这甚至更好,因为我们可以继续使用self而不会实际捕获强引用self.但是,只要我们使用隐式ivars-of-self语法,self就会捕获对"原始"的强引用!
- (void)someMethod
{
@weakify(self);
dispatch_async(self.someQueue, ^{
@strongify(self); /* compiler warning: Unused variable self here!!! */
NSLog(@"self->_testIVar: %@", _testIVar);
}
}
Run Code Online (Sandbox Code Playgroud)
在块中使用ivars时,我们肯定会捕获self.请参阅此屏幕截图:
.
关于屏幕截图的另一个有趣的事情是警告消息
未使用的变量'self'
并在下面的行
在此区块中强烈捕获"自我"可能会导致保留周期
这就是为什么我认为有两个版本self:-)
这里的实际问题是:究竟是什么_testIVar意思?它是如何找到"原始" self指针的?
澄清(也见我的截图):正如@MartinR指出的那样(这也是我的想法),其中有一些特殊版本self无法更改,仅用于隐式自我ivar访问.这是在某处记录的吗?基本上哪里定义了隐含的self含义?它的行为似乎与Java所做的相同(有this),但区别this在于您无法覆盖的保留关键字.
问题也不是如何"修复"它,只是self->_testIVar在@weakify/ @strongify示例中写出我想要的东西.更多的是我通过使用@weakify/ @strongify你不能犯错误的隐含强烈捕获self,但事实上似乎并非如此.
Mar*_*n R 17
所有Objective-C方法都使用两个隐藏参数调用(来自"Objective-C运行时编程指南"):
并且方法可以将接收对象称为self(以及其自己的选择器_cmd).
现在_ivar相当于这个隐含的第一个函数参数self->_ivar在哪里.只要您没有在内部范围中定义新变量,就保持为true.selfself_ivar == self->_ivar
如果您self在内部范围中定义了一个新变量,那么您就拥有了
self,并且_ivar仍然指的是"隐含的自我"!这解释了块中的编译器警告,它们似乎相互矛盾:
self,以下代码也演示了这一点:
@interface MyClass : NSObject
{
NSString *_ivar;
}
@end
@implementation MyClass
- (void)test
{
_ivar = @"foo"; // Set instance variable of receiver
{
MyClass *self = [MyClass new]; // Redefine self in inner scope
self->_ivar = @"bar"; // Set instance variable of redefined self
NSLog(@"%@ - %@", self->_ivar, _ivar);
// Output: bar - foo
}
}
@end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2458 次 |
| 最近记录: |