同一 UITapGestureRecognizer 實例分別添加給 sendView、payView、receiverView、commentView,結果**只有最後添加的 commentView 能響應點擊**。
UIGestureRecognizer **一次只能附屬於一個 View**。當對同一手勢實例呼叫 addGestureRecognizer: 時,系統會**自動從先前的 View 移除**,再添加到新 View。因此前三個 View 實際上並未持有該手勢。
// 方式一:分別建立實例(推薦,語意清晰)
UITapGestureRecognizer *tap1 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(viewClick:)];
[self.sendView addGestureRecognizer:tap1];
UITapGestureRecognizer *tap2 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(viewClick:)];
[self.payView addGestureRecognizer:tap2];
UITapGestureRecognizer *tap3 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(viewClick:)];
[self.receiverView addGestureRecognizer:tap3];
UITapGestureRecognizer *tap4 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(viewClick:)];
[self.commentView addGestureRecognizer:tap4];
- (void)viewClick:(UITapGestureRecognizer *)sender {
UIView *tappedView = sender.view;
if (tappedView == self.sendView) { /* 發送邏輯 */ }
else if (tappedView == self.payView) { /* 支付邏輯 */ }
else if (tappedView == self.receiverView) { /* 收件邏輯 */ }
else if (tappedView == self.commentView) { /* 評論邏輯 */ }
}
在共同父視圖添加手勢,通過 hitTest:withEvent: 判斷點擊落在哪個子視圖。**缺點**:事件傳遞鏈複雜、易與子視圖自身手勢衝突、難以維護。
let views = [sendView, payView, receiverView, commentView]
views.forEach { view in
let tap = UITapGestureRecognizer(target: self, action: #selector(viewClick(_:)))
view.addGestureRecognizer(tap)
}
@objc func viewClick(_ sender: UITapGestureRecognizer) {
switch sender.view {
case sendView: /* ... */ break
case payView: /* ... */ break
case receiverView: /* ... */ break
case commentView: /* ... */ break
default: break
}
}
一個手勢識別器只能綁定一個視圖。多視圖需多實例。這是 UIKit 設計決策,非 Bug。記住:addGestureRecognizer: 會自動從舊視圖移除。