7

私は、静的オブジェクトを作成するためにdispatch_onceを使用するクラスメソッドを持っています。 dispatch_onceブロック内で私は[self class]を使用し、保持サイクルを避けるためにselfの弱い参照を使用する必要があるのだろうかと疑問に思っていましたか?クラスメソッドselfがブロック内で使用される場合

'のconstクラス' タイプの表現で '* __弱いTUAccount'

+ (NSArray *)accountNames{ 
    static NSArray *names = nil; 
    static dispatch_once_t predicate; 
    __weak TUAccount *wself = self; 
    dispatch_once(&predicate, ^{ 
     names = [[[wself class] accounts] allKeys]; 
     names = [names sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; 
    }); 
    return names; 
} 

互換性のないポインタ型の初期化:私はselfに弱い参照を使用している場合

+ (NSArray *)accountNames{ 
    static NSArray *names = nil; 
    static dispatch_once_t predicate; 
    dispatch_once(&predicate, ^{ 
     names = [[[self class] accounts] allKeys]; 
     names = [names sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; 
    }); 
    return names; 
} 

は私が警告を受けます

私は警告を受けるので、私はこの場合にはselfに弱い参照を使う必要はないと思っていますが、私は皆さんの考えを見たいと思っていました。

答えて

11

ここで保持サイクルを心配する理由はありません。これは、クラスオブジェクトを保持または解放する意味がないためです。保持および解放は単に効果がありません。あなたはクラスオブジェクトselfを取り、TUAccountインスタンスにキャストしようとしているので、弱参照を作るのが

あなたの試みは、間違っています。 2つは全く異なるものです。自己が自己==すでにクラス、[自己クラス]であるので、代わりにこれを行うので

names = [[[self class] accounts] allKeys]; 

を::

また、あなたが簡素化できる情報のため

names = [[self accounts] allKeys]; 
+0

ありがとう、なぜ私はいくつかのクラスメソッドに 'self'を使用しても動作しない理由が分かりません。なぜなら私は' [self class] 'を使ってすべてのクラスメソッドを呼び出すのです。 – keegan3d

+3

あなたのクラスメソッド、あるいはアップルのフレームワークにあるクラスメソッド? 「うまくいかない」とはどういう意味ですか?おそらく理由がある。 –

+0

これはメソッドがどこから呼び出されたかに基づいています。 'accounts'クラスメソッドの場合、これは私自身のクラスメソッドです。他のクラスのメソッドから '[self accounts]'で呼び出すことはできますが、インスタンスメソッドでは '[[self class] accounts]'を使わなければなりません。したがって、上のサンプルコードでは、それはちょうど '[self accounts]'である可能性があります。 – keegan3d

0

私は1つの以上の時間のiOS SDKドキュメントをチェックし、次を発見した:

のObjective-Cは、手動カウント基準環境で

オブジェクト、ブロック内で使用されるローカル変数はブロックに保持されていますコピーされます。ブロック内でインスタンス変数を使用すると、オブジェクト自体が保持されます。特定のオブジェクト変数に対してこの動作をオーバーライドする場合は、__blockストレージタイプ修飾子を使用してその動作をマークできます。

ARCを使用している場合、ブロックがコピーされて後で解放されると、オブジェクト変数は自動的に保持され、解放されます。

  • 注:ガベージコレクション環境では、__weak修飾子と__block修飾子の両方を変数に適用すると、そのブロックが確実に生き残っているとは限りません。もしメソッドの実装内のブロックを使用する場合

、オブジェクトのインスタンス変数のメモリ管理のためのルールは、より微妙である:あなたが参照することにより、インスタンス変数にアクセスする場合

  • は、自己が保持されます。
  • インスタンス変数に値でアクセスすると、変数は保持されます。

以下の実施例は、2つの異なる状況を示す:

dispatch_async(queue, ^{ 
    // instanceVariable is used by reference, self is retained 
    doSomethingWithObject(instanceVariable); 
}); 


id localVariable = instanceVariable; 
dispatch_async(queue, ^{ 
    // localVariable is used by value, localVariable is retained (not self) 
    doSomethingWithObject(localVariable); 
}); 

結論:私はブロック内selfの使用に問題がないと仮定する。それは保持され、実行が解放された後に保持されます。

さらに、ブロックをメモリに格納せずに直接使用することもできます。したがって、ヒープにコピーされ、実行され、そこからプッシュされます。私は保持サイクルを見ません。

希望です!

+0

おかげで、それはあります本当に役に立ちました! – keegan3d

+0

'id'はポインタなので、2番目の状況では' localVariable'は 'instanceVariable'と同じオブジェクトを参照していますか? – Elliot

+0

@Elliot新しい値を 'instanceVariable'に設定した場合、' localVariable'は更新されません。 'instanceVariable'が変更可能で変更された場合、' localVariable'は同じ値を参照します。 – Nekto

関連する問題