2012-04-09 10 views
3

Objective-Cで^ブロックを使用していくつかの問題が発生しました。私はブロック内からインスタンス変数を設定しようとしています - 私はこのトピックに関するいくつかのAppleのドキュメントを読みましたが、私はすべてを試したと感じています。^ブロックからプロパティにアクセスすると愚かな動作が発生する

@interface MyClass 
{ 
    // I have tried all possible combinations using __weak, __strong and __block. 
    __weak __block NSMutableArray *filenames; 
} 

// *.m 
static ASIFormDataRequest *g_request = nil; 

@implementation MyClass 
-(void) funnymethod 
{ 
    filenames = [NSMutableArray array]; 
    [filenames addObject:@"This is a string."]; 
    NSLog(@"%@", filenames); 

    g_request = [InitializerClass initializeRequest]; 
    [g_request setCompletionBlock:^ 
    { 
     filenames = [NSMutableArray array]; 
     [filenames addObject:@"This is another string."]; 
     NSLog(@"%@", filenames); 
    }]; 

    [g_object startASynchronous]; 
} 
@end 

上記のコードは、次の出力を与える: ( "これは文字列です。") (ヌル)

吸引します。だから私は__weak、__strong、__blockのさまざまな組み合わせを試しました。他のものは次のような出力を出します: ( "これは文字列です") ( "これは別の文字列です") しかし、大規模だが。完了ブロックは一度も終了しません。上のバーの開いている接続を示すアクティビティインジケータが回転し続け、画面が応答しなくなります。

ファイル名 - オブジェクトをブロック内から正しく設定するにはどうすればよいですか?前もって感謝します。どのような修飾子が何

+0

補完ブロックが完全に空の場合はどうなりますか?私は、ASIFormDataRequestの問題は、このブロックで何をしているかとは何の関係もないと思います。 –

答えて

4

__blockこの修飾子は、クロージャが与えられた変数に格納されている値を変更することができます。

__weakは、がないオブジェクトへの参照です。オブジェクトの割り当てが解除されないようにします。

__strongは、のオブジェクトへの参照であり、オブジェクトの割り当てが解除されないようにします。あなたがする必要がどのような

:現在のスコープが終了した後、それが割り当て解除されてから、あなたの配列を防ぐことはできませんので、あなたが欲しいものを

__weakを行いません。非同期呼び出しを行っているので、ブロックが実行される前に、実行時に配列によって使用されたメモリが再利用されることはありません。

__strongは、現在のスコープの末尾を超えてオブジェクトを保持します。これはあなたが望むものです。

__blockブロックで指定された変数を変更できるようになりますが、selfは自動的に保持されるため、インスタンス変数を参照するときは不要です。

デフォルトでは、ブロック内の Objective-Cオブジェクトを参照すると、参照カウント環境では保持されます。 オブジェクトのインスタンス変数を参照するだけであれば、これも当てはまります。ただし、オブジェクト __blockストレージタイプ修飾子でマークされた変数は、保持されません です。

注:ガベージコレクション環境では、変数に__weak修飾子と __block修飾子の両方を適用すると、そのブロックは確実に有効に保たれません。もし メソッドの実装内でブロックを使用する場合、オブジェクトのインスタンス変数のメモリ管理のためのルールは もっと微妙である:あなたが参照することにより、インスタンス変数にアクセスする場合

は、自己が保持されます。

私はあなたの問題は(太字に関連する部分を)ここにあると思う:

インポート変数があることを指定することができる可変-それは、__blockを適用することにより、読み取り書込み禁止されます記憶域タイプ修飾子。 __blockストレージは、ローカル変数のレジスタ、自動および静的記憶域タイプに似ていますが、相互に排他的です。

__block変数は、変数のレキシカルスコープと、宣言されたすべてのブロックおよびブロックコピーと、変数のレキシカルスコープ内で作成された の間で共有されるストレージに存在します。したがって、フレーム内で宣言されたブロック のコピーがフレームの終わりを超えて生き残った場合(例えば、 の場合は、後で実行するためにキューに入れられることによって)、ストレージはスタックフレームの破壊から生き残ります。与えられたレキシカルスコープのブロック 複数が同時に共有変数 を使用することができます。

最適化として、ブロックストレージはスタックから開始されます( ブロック自体が行うように)。 Block_copyを使用してブロックをコピーした場合(ブロックにコピーが送信されたときに Objective-C)、変数は ヒープにコピーされます。したがって、__block変数のアドレスは の時刻に変更される可能性があります。

は__block変数にさらに2つの制限があります:彼らは は、可変長配列することはできません、とC99 可変長配列を含む構造にすることはできません。代わりにNSMutableArray

+ (id)arrayWithObject:(id)anObjectを使用して、プレーンNSArrayを使用してみてください。

+0

[このドキュメントの]「可変長配列」(https://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Blocks/Articles/bxVariables.html#//apple_ref/doc/uid/TP40007502) -CH6-SW1)は「NSMutableArray」を意味するものではなく、「C99可変長配列」(http://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html)を意味します。あなたは '__block NSMutableArray *'を持つことが許されています。 (ここでは意味がないかもしれませんが、許可されています) –

+0

@KurtRevisが削除されました。 – mydogisbox

+0

ivarを変更するのに '__block'は必要ありません。 ivarsへのアクセスはブロックによってコピーされる暗黙の 'self'変数を経由します。効果的にブロックは 'self-> fileNames = newValue'を行います。 –

関連する問題