iOS/iPhone/iPad/watchOS/tvOS/MacOSX/Android プログラミング, Objective-C, Cocoa, Swiftなど
Objective-C時代にUIViewControllerでBlocksを使う場合は、以下のように、自分の過去のコードをテンプレートのようにしてコピーして使っていた。
__block ViewController * __weak blockWeakSelf = self;
[[Connector sharedConnector] demoWithCompletionHandler:^() {
ViewController *tempSelf = blockWeakSelf;
if (! tempSelf) return;
:
}];
ある条件でのみ呼ばれるBlockの場合、呼ばれない可能性もあり、BlockでViewControllerのselfを強参照で保持すると、画面遷移などでViewControllerが不要になってもメモリの残り続けることになる。そこで、Blockでキャプチャするのはweak selfとし、利用時にnilなら、そのViewControllerは存在しないので、何もしないとしていた。
また、Block内で自身を参照すると、循環参照になるということで、Xcodeで警告されるようになったので、weak selfを記述するようになったと思う。
MyClass * __weak weakSelf = self;
self.block = ^{
[weakSelf hoge];
weakSelf.foo = @"bar";
};
Swiftではweakに加えunownedが使え、前者はnilになる可能性があり、後者はnilにならないとなる。
プロパティの初期化では、自身はnilにならないので、以下のように遅延処理で記述できる。
class MyClass: NSObject {
lasy var block: () -> Void = {
[unowned self] () -> Void in
self.hoge()
}
}
また、コード中は以下のように記述できる。
self.block = {
[unowned self] () -> Void in
self.hoge()
}
最初のViewControllerの場合のように、自身がnilになる可能性がある場合は、weakを選択ということになるのだろう。
self.block = {
[weak self] () -> Void in
guard let self = self else { return }
self.hoge()
self.foo = "bar"
}