一般的な問題
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
一部でオリジナルを隠したとしても、暗黙のivar構文は依然として「オリジナルの」自己を見つけますが、明らかにそうではありません。後者の場合、コンパイラは正しく不平を言いますNSInteger
self
_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
と@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);
}
}
その他
ブロックで ivar を使用する場合、確実に をキャプチャしていますself
。たとえば、次のスクリーンショットを参照してください
。
スクリーンショットのもう 1 つの興味深い点は、警告メッセージが
未使用の変数「自己」
そして下の行で
このブロックで「自己」を強くキャプチャすると、保持サイクルが発生する可能性があります
そのため、2つのバージョンがあると思いますself
:-)
質問
ここでの実際の質問は次のとおりです。正確には_testIVar
どういう意味ですか? 「元の」self
ポインタをどのように見つけるのですか?
明確にするために(私のスクリーンショットも参照してください):@MartinRが指摘したように(これは私もそう思います)、self
変更できず、暗黙的な自己ivarアクセスにのみ使用される特別なバージョンがあります。それはどこかに文書化されていますか?基本的に、暗黙の参照先はどこで定義されていself
ますか? たとえば Java と同じように動作するように見えますが ( を使用)、オーバーライドできない予約済みキーワードであるというthis
違いがあります。this
問題は、それを「修正」する方法でもありません。 /の例self->_testIVar
で私が望むのは、ただ書くだけです。/を使用することで、暗黙的に強力にキャプチャするという間違いを犯すことはできなくなりましたが、そうではないようです。@weakify
@strongify
@weakify
@strongify
self