2013-09-30 70 views
9

幾年來,我一直假設如果一個超級視圖和它的子視圖都具有手勢識別器,那麼子視圖將首先接收觸摸並取消超級視圖的手勢。在iOS 7之前,這個假設永遠不會讓我失望,這讓我可以爲子視圖添加手勢,確信超級景觀的手勢不會干擾。但在iOS 7中,超級視圖會先隨機接收觸摸並取消子視圖的手勢。這種情況很少發生,這使問題很難找到。在iOS 7中,superview的手勢應該取消子視圖的手勢嗎?

我第一次遇到這個問題,因爲按鈕不能使用UITapGestureRecognizer ......再次,很少。通常這些按鈕會一直工作,直到他們沒有。讓你質疑你的理智。所以我推出了我自己的TapGestureRecognizer,發現superview水龍頭有時會取消他們的子視圖的水龍頭。它從來沒有在任何以前的iOS版本中做過,但我想知道這種行爲是否從未承諾過。

我以爲子視圖的手勢應該取消它的超級視圖的手勢(除非委託人另有規定)。這是錯誤的還是這是一個錯誤?

請注意:我不是問如何處理這種情況。我問是否有人知道我的假設是否不正確。我已經重新排列視圖,動態地添加/刪除手勢,並創建相當複雜的gestureRecognizer:shouldReceiveTouch:實現來糾正這種情況。這並不好玩,但我可以解決這個問題。

回答

8

經過大量搜索後,我發現與其他用戶發生此問題的蘋果電子公告板的討論:Issues with UITapGestureRecognizer(需要開發人員帳戶)。我繼續並提交了一個錯誤報告:15331126 (沒有人知道如何鏈接到錯誤報告了嗎?)。與此同時,我實施了這個解決方法。到目前爲止,它似乎正在工作,但由於該錯誤非常罕見,我可能根本沒有觸發它。我將它發佈給我的測試用戶,如果我沒有收到他們的投訴(誰在抱怨),我會認爲這可以解決問題。

UPDATE: 該解決方案解決了這一問題。在幾十個用戶使用數週後,我還沒有一個手勢問題。

我的大部分手勢都是自定義的。我改變了他們是自己的代表和實現:

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

我不完全相信,我需要檢查的兄弟姐妹,我只看到了問題的發生與上海華手勢。但是,我不想冒這個機會。請注意,由於我不想取消當前視圖上方的視圖手勢,因此我只檢查當前視圖的「下方」同胞。

我不得不添加實現了爲自己設定的自定義識別器代表這些階級,但是他們非常簡單,只是回調到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

好東西!現在我發現自己給出了一個冗長的序言,說明我所描述的錯誤如何被任何理智的人認爲是不合理的,並試圖澄清預期與正確不同的觀點。我也有錯誤如預期回來,後來修復 - 不知道如何發生。再次進入違規行爲! ;-) –