多くの検索を行った後、Apple のメッセージ ボードで、この問題を抱えている他のユーザーとのディスカッションを見つけました: UITapGestureRecognizer の問題(開発者アカウントが必要です)。私は先に進み、バグレポートを提出しました: 15331126 (バグレポートにリンクする方法を知っている人はいますか?) . その間、この回避策を実装しました。これまでのところ動作しているようですが、バグは非常にまれであるため、まだトリガーしていない可能性があります。私はそれをベータ版ユーザーにリリースしています。彼らから苦情がなければ (苦情を言っている)、これで問題が解決したと思います。
更新:
このソリューションは問題を修正しました。何十人ものユーザーが数週間使用した後、ジェスチャに関する問題は 1 つもありませんでした。
私のジェスチャーのほとんどはカスタムです。それらを自分自身のデリゲートに変更して実装しました。
- (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
if (gestureRecognizer == self){
if ([otherGestureRecognizer isMemberOfClass:self.class]){
if ([self isGestureRecognizerInSuperviewHierarchy:otherGestureRecognizer]){
return YES;
} else if ([self isGestureRecognizerInSiblings:otherGestureRecognizer]){
return YES;
}
}
}
return NO;
}
私のカスタムのgestureRecognizersは現在、UIGestureRecognizerDelegateプロトコルを実装していることに注意してください(理由は後述します)。また、UIGestureRecognizer (上記のコードで使用) にいくつかのカテゴリを追加しました。
- (BOOL) isGestureRecognizerInSiblings:(UIGestureRecognizer *)recognizer{
UIView *superview = self.view.superview;
NSUInteger index = [superview.subviews indexOfObject:self.view];
if (index != NSNotFound){
for (int i = 0; i < index; i++){
UIView *sibling = superview.subviews[i];
for (UIGestureRecognizer *viewRecognizer in sibling.gestureRecognizers){
if (recognizer == viewRecognizer){
return YES;
}
}
}
}
return NO;
}
- (BOOL) isGestureRecognizerInSuperviewHierarchy:(UIGestureRecognizer *)recognizer{
if (!recognizer) return NO;
if (!self.view) return NO;
//Check siblings
UIView *superview = self.view;
while (YES) {
superview = superview.superview;
if (!superview) return NO;
for (UIGestureRecognizer *viewRecognizer in superview.gestureRecognizers){
if (recognizer == viewRecognizer){
return YES;
}
}
}
}
スーパービュー ジェスチャで問題が発生するのを見ただけなので、兄弟を確認する必要があるかどうかは完全にはわかりません。しかし、私はそのチャンスを逃したくありませんでした。現在のビューの「上」にあるビュー ジェスチャをキャンセルしたくないため、現在のビューの「下」にある兄弟のみをチェックすることに注意してください。
カスタム認識エンジンのデリゲートとして自分自身を設定するクラスの実装を追加する必要がありましたが、ほとんどの場合、それらのクラスはジェスチャレコグナイザーにコールバックするだけです。
- (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
if ([gestureRecognizer respondsToSelector:@selector(gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer:)]){
return [(id <UIGestureRecognizerDelegate>)gestureRecognizer gestureRecognizer:gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:otherGestureRecognizer];
}
return NO;
}
これが問題を抱えている他の誰かに役立つことを願っています。