トップ 最新 追記

Cocoa練習帳

iOS/iPhone/iPad/watchOS/tvOS/MacOSX/Android プログラミング, Objective-C, Cocoa, Swiftなど

2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|

2021-10-10 [Cocoa][Swift]weak self

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"
}

トップ 最新 追記