2015/07/02

UIPopoverPresentationControllerが閉じる際にタップを連打するとアプリが落ちることへの対策

不具合内容

iPadアプリで、あるUITextFieldが選択されると、UIPopoverPresentationControllerでTableViewを表示して選択肢の中からユーザーに項目を選ばせる、という画面を実装していたところ、以下の様な不具合が発生した。

  • タップを連打すると、popoverがcloseするタイミングでエラーも出ずにアプリが落ちる
  • iOS 8.3, 8.4 では発生しない

最新のOSバージョンでは発生しないのでiOSの不具合と思われるが、どうしても対応して欲しいとのリクエストをお客さんからいただいたので、検討してみた。


対応方法

あまり時間を掛けたくなかったので、かなり場当たり的な対応だが、以下の方法で不具合を回避できた。

  • (BOOL)popoverPresentationControllerDidDismissPopover: にて、beginIgnoringInteractionEvents でタッチイベントを無効化する
  • 500ms後に endIgnoringInteractionEvents でタッチイベントを有効に戻す

コード例

#pragma mark - タップ連打防止
/**
 * iOS8.3未満の場合、タップを無効化する
 */
- (void)preventTapBarrage:(float)waitTime
{
  // iOS8.3未満の場合
  if ([[UIDevice currentDevice].systemVersion floatValue] < 8.3){
    // タッチイベントを無効にする
    [[UIApplication sharedApplication] beginIgnoringInteractionEvents];

    // 指定ms後、タッチイベントを有効に戻す
    [NSTimer scheduledTimerWithTimeInterval:waitTime
                                     target:self
                                   selector:@selector(enableTapEvents:)
                                   userInfo:nil
                                    repeats:NO];
  }
}

/**
 * タップを有効に戻す
 */
- (void)enableTapEvents:(NSTimer *)timer
{
  // タッチイベントが無効になっている場合
  if ([[UIApplication sharedApplication] isIgnoringInteractionEvents]){
    // タッチイベントを有効にする
    [[UIApplication sharedApplication] endIgnoringInteractionEvents];
  }
}

#pragma mark - UIPopoverPresentationControllerDelegate Methods
/**
 * iOS8.3未満において、popoverのclose時にタップ連打するとアプリが落ちるため
 * 一時的 (500ms) にタッチを無効化する
 */
- (BOOL)popoverPresentationControllerShouldDismissPopover:(UIPopoverPresentationController *)popoverPresentationController
{
  // 500msタッチ無効 (iOS version < 8.3 の場合のみ)
  [self preventTapBarrage:0.5f];
  return YES;
}

0 件のコメント:

コメントを投稿