5

私はこの問題に数回遭遇しましたが、正しいアプローチを知りたいと思います。

たとえば、iPhoneアプリを作成していて、ブロックを使用するカスタムアラートビュークラスが必要だとします。

だから私はクラスを書き、それから後で私のコードで行きます:

MyAlertView *alert = [MyAlertView alertWithBlahBlahBlah...];
[alert addButton:@"button" withBlock:^{ ... }];
[alert show];

アラートビュークラスのどこかに、

- (void)addButton:(NSString *)button withBlock:(void (^))block {
    [_blocks setObject:[block copy] forKey:button];
}

- (void)show {
    ... drawing stuff ...
    UIButton *button = ...
    [button addTarget:self selector:@selector(buttonPressed:) ...];
    ...
}

- (void)buttonPressed:(id)sender {
    ((void (^)())[_blocks objectForKey:[sender title]])();
}

そのため、アラートビューが正常に表示されるようになりました。問題は、ボタンをタップすると、表示されたオブジェクトにbuttonPressed:セレクターを送信しようとすることです。MyAlertViewただし、MyAlertView現時点では、はスーパービューから削除されています。ARCは、アラートビューはもう誰も所有していないため、ボタンが将来メッセージを送信する必要があることを知らずに、割り当てを解除する必要があると判断しました。これにより、ボタンをタップするとクラッシュが発生します。

アラートビューをメモリに保持する正しい方法は何ですか?オブジェクトをそれを使用しているクラスのプロパティにすることはできMyAlertViewますが、それはちょっとばかげています(一度に2つのアラートを表示したい場合はどうなりますか?)。

4

3 に答える 3

7

オブジェクトがメモリに残っていて、そのオブジェクトへの参照がない場合、これはメモリリークと呼ばれます。コメントで述べたように、a)割り当てが解除されないように、b)メッセージを送信できるように、c)クラスの割り当てが解除される前に割り当てを解除できるように、何らかの参照を保持する必要があります。

これを行う最も明白な方法は、クラスのプロパティを使用することです。あなたはそれをしたくないと言ったので(多分あなたはそれらをたくさん持っているでしょう)、別の可能な解決策はあなたが再利用して最終的に割り当てを解除することを計画しているキャッシュされたオブジェクトの配列を保持することです。

于 2012-07-25T03:46:45.867 に答える
1

performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delayrunloopでアラートビューを保持するために使用できると思います。

実際、私はこのスキルを使用したUIAlertViewのラッパー実装に出くわしました。

詳細については、 UIAlertView入力ラッパーを確認してください。

于 2012-07-25T03:52:16.793 に答える
1

簡単に言えば、あなたはメモリ管理のルールを破っています。ARCはルールを変更せず、ルールを自動化するだけです。生き続けるためにオブジェクトが必要な場合は、所有者が必要です。アプリのオブジェクトグラフ内のすべてのオブジェクトには、アプリケーションデリゲートまでさかのぼって、所有者がいます。その所有者が何であるかは明らかではないかもしれませんが(場合によっては所有者が自動解放プールである可能性があります)、1つあります。

このビューを維持したい場合は、「現在使用されていない」場合でも、何かが所有している必要があります。画面に表示されている場合は、ビュー階層の一部である必要があります。そうでない場合、理想的な所有者はそれを作成したオブジェクトである可能性があります。

于 2012-07-25T04:04:33.790 に答える