5

UIAlertViewエラーが発生した場合はAが表示されます。しかし、その間に、UIAlertView呼び出されたビューは却下されました (したがって、リリースされました)。ユーザーが [OK] をクリックすると、リリースされたインスタンスへのメッセージが送信されるため、アプリがクラッシュします。これにより、アプリがクラッシュします。

UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"test" message:@"test" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertView show];
[alertView release];
alertView = nil;
[self.navigationController popViewControllerAnimated:YES];

UIAlertViewは独立したユニットだと思いました。しかし、そうではないようです。アプリのクラッシュを回避する方法はありますか (ビューを閉じない場合を除く)。

4

6 に答える 6

10

UIAlertViewが却下されたときにデリゲートが呼び出されるため、あなたの場合は次のようになります。

delegate:self

デリゲートは、配列に追加されたオブジェクトやサブビューのように保持されません。したがって、あなたの場合、電話すると:

[self.navigationController popViewControllerAnimated:YES];

self解放されている可能性が高く、ユーザーがアラートをself閉じると呼び出されますが、割り当てが解除されたため、存在しなくなります。

これを確認する簡単な方法は、のメソッドのようNSLog(@"I'm gone");にlogger ステートメントを配置することです。これが実行された場合、もう存在しないことがわかり、メッセージが送信されるとクラッシュが発生します。selfdeallocself

于 2010-10-14T23:24:14.330 に答える
5

UIAlertView をビュー コントローラーの保持プロパティにして、dealloc で参照できるようにし、ビュー コントローラーの割り当てが解除されたときにアラート ビューのデリゲートを nil に設定します。

保持されたアラート ビューが閉じられて解放されたら、必ず適切に解放してください。

例えば:

@interface MyViewController : UIViewController <UIAlertViewDelegate> {
    UIAlertView *alertView;
}

@property (nonatomic, retain) UIAlertView *alertView;



@implementation MyViewController

@synthesize alertView;

- (void)showAlert {
    if (alertView) {
        // if for some reason the code can trigger more alertviews before
        // the user has dismissed prior alerts, make sure we only let one of
        // them actually keep us as a delegate just to keep things simple
        // and manageable. if you really need to be able to issue multiple
        // alert views and be able to handle their delegate callbacks,
        // you'll have to keep them in an array!
        [alertView setDelegate:nil];
        self.alertView = nil;
    }
    self.alertView = [[[UIAlertView alloc]
                       initWithTitle:@"Error"
                       message:@"Something went wrong"
                       delegate:self
                       cancelButtonTitle:@"Cancel"
                       otherButtonTitles:@"Retry",nil] autorelease];
    [alertView show];
}

- (void)alertView:(UIAlertView *)alertViewParam didDismissWithButtonIndex:(NSInteger)buttonIndex {
    self.alertView = nil; // release it
    // do something...
}

- (void)dealloc {
    [alertView setDelegate:nil]; // this prevents the crash in the event that the alertview is still showing.
    self.alertView = nil; // release it
    [super dealloc];
}

ここでの欠点は、ユーザーがアラート ビューを閉じたときに、アラート ビューのコールバックを処理できないことです。ただし、コントローラーは既になくなっている/リリースされているため、おそらくその必要はありません。その場合、アラート ビューのデリゲートを持続するものに設定する必要があります。

于 2012-03-22T06:09:06.297 に答える
1

私にとってより簡単な方法は、すべてのアラートビューを配列に保持し、親ビューの割り当てが解除されたら、alertViews 配列を列挙し、デリゲートを nil に割り当てることです。これにより、タッチ イベントが無視され、アプリが機能することが保証されます。

// ARC world

@property (strong, nonatomic) NSMutableArray *alertViews;

- (void)dealloc
{
    [self.alertViews makeObjectsPerformSelector:@selector(setDelegate:) withObject:nil];
}
于 2013-10-03T22:15:26.047 に答える
1

(People might wonder I am late by years in answering this question,but it might help someone else)

I guess your problem lies some where in popping the view controller,you are displaying the alert view and at the same time trying to navigate the user back to a view.I would recommend you to follow a hierarchal approach here i.e.:

First of all declare your alert view as a global object,i.e.

@property(nonatomic,retain) UIAlertView *sampleAlert;

Now write your alert view display code where ever desired,say for instance:

-(IBAction)buttonClicked:(id)sender
{
  self.sampleAlert = [[UIAlertView alloc] initWithTitle:@"test" message:@"test" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
  [sampleAlert show];
  [sampleAlert release];
}

Finally try to navigate the user to the desired view when the "Ok" button is pressed,i.e. you need to make use of alertView didDismissWithButtonIndex method,i.e.

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex 
{
   if(alertView == sampleAlert)
   {
     [self.navigationController popViewControllerAnimated:YES];
   }
}

Please note that if you have alert view with multiple buttons,you also need to check for button index for distinguishing actions,i.e. check using

if(alertView == sampleAlert && buttonIndex == 0)
{
  //Do your stuff
}
else
{
  //Do something else
}

This will definitely avoid application crash,thanks :)

于 2013-09-06T08:16:20.247 に答える
1

UIAlertView オブジェクトを、現在のビューだけでなく、アプリのどこからでも使用できるようにする場合は、アプリのどこからでも利用できる何かの中に保持します。可能なビュー スタック全体の下にある永続的なルート ビュー コントローラー、またはアプリのデリゲート。

追加した:

この最上位オブジェクトは、アラート ビューのデリゲートが必要になるまで (アラート ビューの破棄後) 保持することもできます。

于 2010-10-14T23:24:18.340 に答える
-2

UIAlertViewDelegateプロトコルを実装していることを確認してください。アラートがいつ無視されるかを気にしない場合は、デリゲート as で初期化してnilください。

UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"test" message:@"test" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
于 2010-10-14T23:16:00.513 に答える