5

強いキーワードと弱いキーワードはよく理解していると思いますが、以下のコードでどのように使用されているのかわかりません。このコードは、githubで入手可能なOlivierPoitreyによるSDWebImageからのものです。ここで説明されているように、強いキーワードと弱いキーワードを理解しています:iOS5の強いストレージと弱いストレージの説明

以下のコードは、私が興味を持っている方法で__weakおよび__strongキーワードを使用しています。私は弱い使用を見るのに慣れているので、それは子供と親の関係や委任パターンではありません。ただし、他のコードで以前に見たように、これは頻繁に使用されるパターンであると確信しています。別のスレッドで実行されるブロックの前に__weak参照を設定します。次に、ブロック内で、弱参照を強参照に設定します。

私はこの優れたエレガントなコードを確信しているので、それを理解しようとしています。ブロックが実行される前に「自己」が存在しなくなると、弱い自己参照はゼロになります。ブロックが実行されると、ストロングリファレンスもゼロに設定されます。したがって、自己はもう存在しないので、残りの操作を強制終了することがわかります。私はこれを正しく理解しましたか?

さて、__weakキーワードと__strongキーワードを使用しなかった場合はどうなるでしょうか。ブロック内でself==nilかどうかをチェックした場合はどうなりますか。ブロックがツリー全体をコピーするので、「自己」がゼロになることはありませんか?

誰かがこの素晴らしいコードの謎を解くのを手伝ってもらえますか?誰かが私の仮説を検証または否認できますか?

- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedBlock)completedBlock;
{
    [self cancelCurrentImageLoad];

    self.image = placeholder;

    if (url)
    {
        __weak UIImageView *wself = self;
        id<SDWebImageOperation> operation = [SDWebImageManager.sharedManager downloadWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished)
        {
            __strong UIImageView *sself = wself;
            if (!sself) return;
            if (image)
            {
                sself.image = image;
                [sself setNeedsLayout];
            }
            if (completedBlock && finished)
            {
                completedBlock(image, error, cacheType);
            }
        }];
        objc_setAssociatedObject(self, &operationKey, operation, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
}
4

2 に答える 2

7

このdownloadWithUrl:方法には時間がかかる場合があります。そのとき、ユーザーは離れて移動することを決定し、SDWebImageオブジェクトの必要性を排除する可能性があります。オブジェクトの早期クリーンアップを容易にするために、外部self参照は弱くなります。このように、の割り当てが解除されるdownloadWithUrlのを防ぐことはできませんSDWebImage

もちろん、実際に作業したい場合selfは、強力なリファレンスが必要です。したがって、完了時のブロックはdownloadWithUrl、への強力な参照を取得しselfます。この間にオブジェクトが消えると、sselfになりますnil。それ以外の場合は、オブジェクトがまだ存在していることを示す有効な強力な参照にSDWebImageなり、オブジェクトはこの時点で作業を終了します。

于 2013-02-16T07:35:47.460 に答える
3

私はこの優れたエレガントなコードを確信しているので、それを理解しようとしています。ブロックが実行される前に「自己」が存在しなくなると、弱い自己参照はゼロになります。ブロックが実行されると、ストロングリファレンスもゼロに設定されます。したがって、自己はもう存在しないので、残りの操作を強制終了することがわかります。私はこれを正しく理解しましたか?

いいえ、あなたはこれをかなり考えすぎています。__weakストレージ修飾子はまさにそれです:修飾子。明示的に保持されていないオブジェクトですが__weak、強力な変数から割り当てられた場合、自動的にnilに設定されるだけではありません。実際、それは弱い変数の目的を無効にするでしょう!

さて、__weakキーワードと__strongキーワードを使用しなかった場合はどうなるでしょうか。ブロック内でself==nilかどうかをチェックした場合はどうなりますか。ブロックがツリー全体をコピーするので、「自己」がゼロになることはありませんか?

ランタイムはメッセージをnilからnilに解決するため、チェックは実際には不要です(それでも、後で実装することが重要になる可能性があります)。あなたはこれにスポットを当てています:そこにその小さな「弱いから強い」ダンスがなければ、自己はブロックによって保持され、かなり厄介な保持サイクルを作成する可能性があります。これをすべて一緒に結び始めることができる場所です:

ブロックに変数を保持させたくないが、ブロックのスコープ内で強力にし、奇妙なことが起こらないようにしたいので、selfは弱いポインターに割り当てられます。弱いポインタでブロックが発生すると、それを保持することは許可されないため、自己の参照カウントは同じままです。ブロック内に入ると、すぐに強い自己変数に戻り、弱いポインタが解放されます。もう心配する必要はありません。実際には、これは、ブロックの実行全体を通じて、selfがvalueまたはnilのいずれかであるという確固たる保証があることを意味します。かなりきちんとしていますね

于 2013-02-16T07:38:39.847 に答える