0

テーブル ビューの行が選択されたときにアラートを表示し、そのアラートが消えるまで待機するコードがあります。iOS 5 および 6 を搭載した iPad では問題なく動作しますが、iOS 7 ではアラートを無視しようとしてスタックします。

この問題を説明するために、単純なマスター/詳細アプリを作成し、UIAlertView を拡張して UIAlertViewDelegate に準拠する単純な MyAlert クラスを作成しました。

@interface MyAlert : NSObject <UIAlertViewDelegate>
{
    volatile BOOL completed;
    UIAlertView * alert;
}

- (void) showAndWaitUntilDone:(NSString*)message;

@終わり

MyAlert.m:

@implementation MyAlert

- (void) showAndWaitUntilDone:(NSString*)message
{
    alert = [[UIAlertView alloc] initWithTitle:@"Alert"
                                         message:message
                                        delegate:nil
                               cancelButtonTitle:@"Cancel"
                               otherButtonTitles:@"Other", nil];

    if (alert)
    {
        alert.delegate = self;
        [self showAndWaitUnitlDone];
    }
}

- (void) showAndWaitUnitlDone
{
    completed = NO;
    [alert show];
    while (!completed)
    {
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
                                 beforeDate:[NSDate distantFuture]];
    }
}

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
    completed = YES;
}

@end

次に、次のように ViewController にアラートを表示します。

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [MyAlert showAndWaitUntilDone:@"test msg"];
}

の効果: UIAlertView が iOS 7 でスタックする

前述のように、これは iOS 5 および 6 で問題なく動作します。

メイン スレッドをブロックしなければ、すべて正常に動作するように見えますが、たとえば UIButton コールバックからこのコードを実行すると、うまく動作します。

4

2 に答える 2

2

私だけかもしれませんが、そもそもこれはデザインが悪いように思えます。不明な時間、メイン スレッドをロックしています。
単純に didSelectRowAtIndexPath にアラートを表示させ、アラート コールバック (alertView:clickedButtonAtIndex:) に待機していた残りの作業を行わせません (またはそれを行う関数を呼び出します)。必要に応じて、変数を使用してタップされたエントリを保存します...これにより、メインスレッドを拘束するというマイナス面を防ぎながら、目的の効果が得られるようになります。

Apple がアプリ デザイナーがメイン スレッドをロックするのを防ぐ何かを実装したとしても、私は驚かないでしょう (これが、waitUntilDone: が NO に設定されている場合にのみコードが機能し、本質的にコードを非同期呼び出しに置く理由です)。

于 2013-09-30T15:49:25.927 に答える