web-dev-qa-db-ja.com

弱い自己参照の一般的なタイプ

typeofを使用して、保持サイクルを回避するためにブロックで使用するselfへの弱い参照を作成する方法を見つけようとしています。

私がこれについて最初に読んだとき、慣習は__block typeof(self) bself = self;を使用することでしたが、それはコンパイルしますが、保持サイクルを避けるために___block_を使用することはもはや機能せず、代わりに___weak_を使用する必要があります。

ただし、__weak typeof(self) bself = self;はエラーになります。

タイプ 'typeof(self)'(別名 'TUAccountsViewController * const __strong')にはすでに保持属性が設定されています

typeofまたは別の呼び出しを使用して一般的にselfへの弱い参照を作成する方法はありますか?

34
keegan3d

これは動作します!

__typeof__(o) __weak

BBlockプロジェクトでBBlockWeakSelfとして定義したものは、次のように使用できます。

BBlockWeakSelf wself = self;

https://github.com/kgn/BBlock/blob/master/BBlock.h

Aleph7の応答に基づいて編集されました。

32
keegan3d

最新のclangバージョンApple clangバージョン4.0(tags/Apple/clang-421.1.48)(LLVM 3.1svnに基づく)、つまりXcode 4.4 +__typeof__((__typeof__(self))self)トリックはもう必要ありません。 __weak typeof(self) bself = self;行は問題なくコンパイルされます。

37
0xced

これを行う正しい方法は

__weak ActualClassName* weakSelf = self;

マクロは、コードに移植性のないメタ言語を追加することに加えて、変数が実際に何であり、実際にそれで何をしているのかを不明確にするだけです。

ActualClassNameが提供するよりも汎用的なクラスのバージョンが必要な場合は、selfが定義されているため、selfのクラスも定義されているため、selfを処理しません。定義済み。

そのような場合、継承ツリーで最も近いベースクラス名を使用する必要があります。NSObject以上、決してidを使用しないでください。

__weak MyBaseClassName* weakObject = object;
18
Brane

一般的な弱参照(インポート不要+スニペット)


私の経験では、行く方法は以下を使用することです:

__typeof__(self) __weak weakSelf = self;

所有権修飾子が実際の変数の前にどのように属するかに注意してください。

それが使用されると何が起こるかは非常に明白であり、Xcodeで便利なコードスニペットにでき、これが必要なプロジェクトまたはクラスでさらに使いやすくなります。 (スニペットの補完ショートカットとして「ws」を使用します)

うーん..ここに弱い参照が必要です。

_ws{return}_

できたこのために将来のプロジェクトにヘッダーを含める必要はなく、スニペットを使用するだけです。


Xcodeスニペット


タイトル:_Generic Weak Self Reference_
プラットフォーム:All
言語:_Objective-C_
完了ショートカット:ws
完了スコープ:_Function or Method_
コード:__typeof__(self) __weak weakSelf = self;


Edit: comments およびXcode Snippet Infoに基づく所有者修飾子の位置に関するメモを追加

16

私はこれを使用して大丈夫だと思う:

__weak __typeof(&* self)weakSelf = self;

aFNetworkingのAFURLConnectionOperation.mコードを参照します。

3
kitsionchen

なぜ使用しないのですか

__weak id bself = self;
3
Denis Mikhaylov

C言語の方言をチェックしてみましたか?

Project Navigator-> Project-> Target-> Build Settingsに移動します

C言語の方言を探します。 c11からGNU99に変更します。

私はそれが役立つことを願っています:)

2
Ricardo Anjos

このマクロがあります

#define weaken(object) __typeof__(self) __weak weakSelf = object

そして、私はこのように使用します

weaken(self);
//The block referencing weakSelf goes here
1
Maciej Swic

declareBlockSafe(self)その後、ブロック内でblk(self)。 Selfは、任意の変数またはインスタンス変数です。プロパティとメソッドの戻り値にはdeclareBlockSafeAsを使用します。

Mike Ashの素晴らしいMAZeroingWeakRefをインポートすると、ARC以外でも動作します。 https://github.com/mikeash/MAZeroingWeakRef

#if __has_feature(objc_arc)

#define declareBlockSafe(__obj__) __weak typeof(__obj__) __tmpblk##__obj__ = __obj__
#define blockSafe(__obj__) __tmpblk##__obj__
#define blk(__obj__) blockSafe(__obj__)

#define declareBlockSafeAs(__obj__, __name__) \
__weak typeof((__obj__)) __tmpblk##__name__ = (__obj__)

#else

#define declareBlockSafe(__obj__) MAZeroingWeakRef *__tmpblk##__obj__ = [MAZeroingWeakRef refWithTarget:__obj__]
#define blockSafe(__obj__) ((typeof(__obj__))__tmpblk##__obj__##.target)
#define blk(__obj__) blockSafe(__obj__)

#define declareBlockSafeAs(__obj__, __name__) \
MAZeroingWeakRef *__tmpblk##__name__ = (__obj__)
#endif
</ code>

ARCにはblk()は本当に必要ありません。マクロを非ARCでも同じように使用できるようにするためです。

1
SeruK

__unsafe_unretainedはどうですか?それは__weakほど安全ではありませんが、私が考えることができるのはそれだけです。また、なぜtypeof()を使用するのですか?

0
lbrndnr