2013-09-30 2 views
9

몇 년 동안 저는 수퍼 뷰와 서브 뷰 모두에 제스처 인식기가있는 경우 서브 뷰가 먼저 터치를 받고 슈퍼 뷰의 제스처를 취소한다는 가정하에 작동했습니다. iOS 7까지는이 가정이 절대로 실패하지 않았기 때문에 superview의 제스처가 간섭하지 않을 것이라고 확신하는 하위 뷰에 제스처를 추가 할 수있었습니다. 그러나 iOS 7에서는 수퍼 뷰가 무작위로 터치를 받고 하위 뷰의 동작을 취소합니다. 이 문제는 다소 드물게 발생하며 문제가 발생하기 쉬워졌습니다.superview의 제스처가 iOS 7에서 하위보기의 제스처를 취소해야합니까?

처음에는이 문제를 UITapGestureRecognizer ...을 사용하여 도청 할 수없는 단추로 경험했습니다. 매우 드문 경우입니다. 일반적으로 버튼은 제대로 작동하지 않을 때까지 작동합니다. 당신의 온건함에 대해 질문을 던지게했습니다. 그래서 나는 내 자신의 TapGestureRecognizer을 굴려 슈퍼 뷰 탭이 때로 서브 뷰의 탭을 취소하고 있음을 발견했습니다. 이전 버전의 iOS에서이 작업을 수행 한 적이 없지만이 동작이 단순히 약속 된 것인지 궁금합니다.

나는 하위보기의 제스처가 슈퍼 뷰의 제스처를 취소해야한다고 생각했습니다 (대리인이 별도로 지정하지 않는 한). 잘못 되었나요? 아니면 버그입니까?

참고 : 나는 상황을 어떻게 처리할지 묻지 않습니다. 나는 내 가정이 부정확한지 아무도 모른다면 묻고있다. 이미 뷰를 재정렬하고 제스처를 동적으로 추가/제거하고 상황을 해결하기 위해 다소 복잡한 구현 인 gestureRecognizer:shouldReceiveTouch:을 작성합니다. 재미 있지는 않지만 문제를 해결할 수 있습니다.

답변

8

많은 질문을 한 후이 문제가있는 다른 사용자와 Apple의 게시판에 대한 토론을 발견했습니다 : Issues with UITapGestureRecognizer (개발자 계정 필요). 나는 계속해서 버그 보고서를 제출했다 : 15331126 (더 이상 버그 보고서에 연결하는 방법을 아는 사람이 있습니까?). 그동안이 해결 방법을 구현했습니다. 지금까지는 작동하는 것처럼 보이지만 버그가 너무 드물기 때문에 아직 트리거하지 않았을 수 있습니다. 나는 그것을 베타 사용자들에게 공개 할 것이고, 그들로부터 아무런 불만이 없다면 (불평하고있는) 나는이 문제를 수정한다고 생각할 것이다.

는 UPDATE : 이 해결책은 문제를 해결하고있다. 수십 명의 사용자가 몇 주 동안 사용하고 나면 제스처에 대해 한 가지 문제가 발생하지 않았습니다.

대부분 제 제스처는 관습입니다. 나는 자신의 대표와 수를 변경 구현 : (이유는 아래에서 볼 수, 공개적으로) 내 사용자 지정 gestureRecognizers 이제 UIGestureRecognizerDelegate 프로토콜을 구현

- (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; 
} 

참고.

- (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; 
      } 
     } 
    } 
} 

내가 난 단지 문제가 수퍼 제스처 발생 보았 듯이 형제를 확인 할 필요가 전혀 확실하지 않다 : 나는 또한 (위의 코드에서 사용) UIGestureRecognizer에 범주의 몇 가지를 추가했다. 그러나 나는 그 기회를 포기하고 싶지 않았다. 현재 뷰의 "위"에있는 뷰 제스처를 취소하고 싶지 않기 때문에 현재의 "아래"형제 만 확인합니다.

나는 사용자 지정 인식기의 대표로 자신을 설정하는 클래스에 대한 구현을 추가했지만, 그들은 거의 바로 다시 gestureRecognizer에 호출이 다른 사람이 문제를 가지고하는 데 도움이

- (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{ 
    if ([gestureRecognizer respondsToSelector:@selector(gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer:)]){ 
     return [(id <UIGestureRecognizerDelegate>)gestureRecognizer gestureRecognizer:gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:otherGestureRecognizer]; 
    } 
    return NO; 
} 

희망.

+0

모선에서 의견이 있으십니까? 주문을 수립하기위한 더 명확한 방법/프로토콜을 갖는 것이 더 좋을 것입니다. (그리고 귀하의 게시물에 대한 감사) –

+0

아니, 정말로. 내가 제출 한 레이더는 결국 의도 된 행동으로 제거되었습니다. 그러나 최근 버전의 iOS에서 팝업 문제를 보지 못했기 때문에 내부적으로 수정 된 것으로 의심됩니다. –

+0

좋은 물건! 나는 지금 내가 묘사하고있는 버그가 어떻게 정상인에게 합리적이라고 생각할 수 없었는지에 대한 긴 머리말을하고 기대했던 것이 정확한 것과 같은 것이 아님을 분명히하려고 노력하고있다. 나는 또한 버그가 예상대로 돌아 왔고, 나중에 수정되었는데 - 어떻게되는지는 확실치 않습니다. 한번 더 위반에! ;-) –

관련 문제