Bạn có thể đính kèm một UIGestureRecognizer cho nhiều chế độ xem không?


228
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapTapTap:)];
[self.view1 addGestureRecognizer:tapGesture];
[self.view2 addGestureRecognizer:tapGesture];
[tapGesture release];

Trong mã trên chỉ có vòi trên view2được công nhận. Nếu tôi nhận xét ra dòng thứ ba thì vòi view1được nhận ra. Nếu tôi đúng và bạn chỉ có thể sử dụng một trình nhận dạng cử chỉ một lần, tôi không chắc đây có phải là lỗi không hay nó chỉ cần thêm một số tài liệu.

Câu trả lời:


334

A UIGestureRecognizerlà được sử dụng với một chế độ xem duy nhất. Tôi đồng ý các tài liệu là đốm. Điều đó UIGestureRecognizercó một viewtài sản duy nhất cho nó đi:

lượt xem

Chế độ xem nhận dạng cử chỉ được đính kèm. (chỉ đọc)

@property (nonatomic, readonly) UIView * xem

Thảo luận Bạn đính kèm (hoặc thêm) một trình nhận dạng cử chỉ vào một đối tượng UIView bằng phương thức addGestureRecognizer :.


11
Bởi vì việc thêm một trình nhận dạng cử chỉ vào một khung nhìn xảy ra trong thời gian chạy (so với thời gian biên dịch).
TomSwift

1
Tôi hiểu điều đó, nhưng giống như phát hiện ra rằng chúng tôi đã sử dụng một biến, XCode có thể cho biết dựa trên mã mà chúng tôi đã chuyển cùng một bộ nhận dạng cho nhiều chế độ xem và có thể cảnh báo cho người viết mã.
Zoltán Matók

1
Trình biên dịch cảnh báo về nhiều chế độ xem cùng một UITapGestureRecognizer là vô nghĩa, bởi vì bạn có thể muốn làm điều này trên mục đích, ví dụ nếu bạn muốn di chuyển trình nhận dạng cử chỉ nhấn từ chế độ xem này sang chế độ xem khác. Điều đó nói rằng, đó là một hạn chế ngớ ngẩn rằng trình nhận dạng cử chỉ có thể được sử dụng trên nhiều chế độ xem.
Erik van der Neut

1
iOS 9 hiện thực thi một chế độ xem cho mỗi trình nhận dạng cử chỉ, tôi đã sử dụng phương thức xây dựng giao diện bên dưới, nhưng bây giờ tôi nhận được thông báo sau khi tôi cố gắng sử dụng nó (một số chi tiết bị cắt cho ngắn gọn): CẢNH BÁO: Trình nhận dạng cử chỉ (< UITapGestureRecognizer: .....>) đã được thiết lập trong bảng phân cảnh / xib để được thêm vào nhiều chế độ xem (-> <UIView :; frame = (0 44; 600 536); autoresize = RM + BM; cử chỉ cử chỉ = < NSArray ...:>; layer = <CALayer: ... >>) tại một thời điểm, điều này không bao giờ được cho phép và hiện được thi hành. Bắt đầu với iOS 9.0, nó sẽ được đặt ở chế độ xem đầu tiên mà nó được tải vào.
George Brown

Nếu bạn đang thêm để xem ở lần thứ hai, thì chế độ xem được đính kèm trước đó bởi trình nhận dạng này sẽ tự động không bị ràng buộc UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didPressed:)]; [self.view1 addGestureRecognizer:tapRecognizer]; [self.view2 addGestureRecognizer:tapRecognizer];Đầu ra view1 không có mảng nhận dạng cử chỉ; view2 đã có mảng nhận dạng cử chỉ
kokos8998

48

Tôi đã khắc phục nó bằng cách sử dụng dưới đây.

for (UIButton *aButton in myButtons) {

            UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)];
            longPress.minimumPressDuration=1.0;
            [aButton addGestureRecognizer:longPress];
            [longPress release];

}

Sau đó, trong phương thức xử lýLongPress của tôi, tôi chỉ đặt một UIButton bằng với chế độ xem của trình nhận dạng cử chỉ và phân nhánh những gì tôi làm dựa trên nút đó

- (void)handleLongPress:(UILongPressGestureRecognizer*)gesture {
    if ( gesture.state == UIGestureRecognizerStateEnded ) {
        UIButton *whichButton=(UIButton *)[gesture view];
        selectedButton=(UIButton *)[gesture view];
    ....
}

1
Câu trả lời tuyệt vời. Cảm ơn một tấn. Đây có thể là câu trả lời được chấp nhận nếu câu hỏi là "Làm thế nào bạn đính kèm một UIGestureRecognizer vào nhiều chế độ xem?"
D_D

7
Điều này (hoặc một cái gì đó rất gần với điều này) không làm việc cho tôi. Tôi đã thêm một số chế độ xem vào trình nhận dạng cử chỉ nhấn trong Trình tạo giao diện và kết nối trình nhận dạng với một hành động. Hành động được gọi bất cứ lúc nào một chế độ xem đính kèm đã được khai thác, nhưng cử chỉ.view luôn là chế độ xem cuối cùng được đính kèm.
Aneil Mallavarapu

Đây thực sự là một câu trả lời hay và cũng thực sự hữu ích và đồng ý với @MicRO +1
Dilip

2
Aneil, đó là vì bạn đã không tạo ra các phiên bản mới của trình nhận dạng cử chỉ. Điều xảy ra trong vòng lặp trong câu trả lời này ở đây là các trường hợp nhận dạng cử chỉ mới được tạo ra, mỗi trường hợp chỉ có một khung nhìn được đính kèm. Tất cả đều có thể trỏ đến cùng một trình xử lý, nơi bạn sau đó kiểm tra chế độ xem để xem cái nào được chạm vào.
Erik van der Neut 27/08/2015

1
Người khác có thể xác nhận rằng tính năng này không còn hoạt động trong phiên bản Obj-C / Swift hiện tại không?
Maxi Mus

18

Đối với Swift 3 trong trường hợp bất cứ ai cũng yêu cầu điều này: Dựa trên câu trả lời của Bhasta Rathod ở trên.

 func setGestureRecognizer() -> UIPanGestureRecognizer {

        var panRecognizer = UIPanGestureRecognizer()

        panRecognizer = UIPanGestureRecognizer (target: self, action: #selector(pan(panGesture:)))
        panRecognizer.minimumNumberOfTouches = 1
        panRecognizer.maximumNumberOfTouches = 1
        return panRecognizer
    }

        ///set the recognize in multiple views
        view1.addGestureRecognizer(setGestureRecognizer())
        view2.addGestureRecognizer(setGestureRecognizer())

3
về cơ bản đó là tạo ra nhiều cử chỉ cho hai chế độ xem, vẫn cùng một quy tắc: mọi cử chỉ chỉ có một chế độ xem được đính kèm
Abdoelrhman

3
Không, chức năng tạo một cử chỉ mỗi khi nó được gọi
Abdoelrhman

2
tên của hàm không đúng hàm logic ở đây là hàm nhận. vì vậy nó nên được đặt tên: getGestureRecognizebởi vì đó là những gì chức năng này làm
David Seek

Làm việc tốt cho tôi! Và mã sạch hơn là tạo nhiều biến hoặc đặt toàn bộ mã để tạo bên trong addGestureRecognizer
Codenator81

11

Chúng ta có thể làm một cái gì đó như thế này, thật dễ dàng và đơn giản

1) tạo chức năng như dưới đây trong bộ điều khiển của bạn (chức năng này sẽ trả về GestureRecognizer)

-(UITapGestureRecognizer*)setRecognizer{
     UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(openProfile)];
     [gestureRecognizer setNumberOfTapsRequired:1];
     return gestureRecognizer;
}

2) bây giờ đặt trình nhận dạng này trong nhiều chế độ xem

[self.view1 addGestureRecognizer:[self setRecognizer]]; 
[self.view2 addGestureRecognizer:[self setRecognizer]];

Nó không hoạt động với tôi khi tôi sử dụng hai nhãn thay vì lượt xem.
Mihir Oza

3
@Mihir Oza, nó không thể hoạt động trực tiếp cho UILabels. Bởi vì các nhãn không có ý nghĩa cho tương tác người dùng. Nếu bạn muốn thêm cử chỉ cho UILabels, hãy thêm dòng tên nhãn này..isUserInteractionEnables = true trong Swift. Sau đó thêm cử chỉ.
iOS

Đã quá muộn rồi, tôi đã sửa nó rồi. Nhưng cảm ơn vì lời đề nghị. Nhận xét của bạn sẽ hữu ích cho người dùng ngăn xếp. Đánh giá cao!
Mihir Oza

1
Tôi đoán đường dây setNumberOfTapsRequired:1là không cần thiết
Naveed Abbas

9

Không, bạn không nên đính kèm nhận dạng cử chỉ vào nhiều hơn một chế độ xem.

Có thông tin rõ ràng này trong tài liệu của Apple:

Công nhận cử chỉ được đính kèm với một khung nhìn

Mỗi nhận dạng cử chỉ được liên kết với một chế độ xem. Ngược lại, một chế độ xem có thể có nhiều nhận dạng cử chỉ, bởi vì một chế độ xem có thể đáp ứng với nhiều cử chỉ khác nhau. Để trình nhận dạng cử chỉ nhận biết các lần chạm xảy ra trong một chế độ xem cụ thể, bạn phải gắn trình nhận dạng cử chỉ vào chế độ xem đó.

Hướng dẫn xử lý sự kiện cho iOS - Trình nhận dạng cử chỉ Thư viện nhà phát triển của Apple

Trong khi như những người khác đề cập, họ có thể làm việc trong một số trường hợp rõ ràng là trái với tài liệu và có thể thay đổi trong bất kỳ phiên bản iOS nào trong tương lai.

Những gì bạn có thể làm là thêm các nhận dạng cử chỉ riêng biệt vào các chế độ xem bạn muốn theo dõi và chúng có thể chia sẻ một hành động chung.


4

Chà, nếu ai đó không muốn mã để thêm chế độ xem cử chỉ cho nhiều nút như kwalker đã trả lời ở trên và muốn thực hiện thông qua Trình tạo giao diện, điều này có thể giúp bạn.

1) Bạn có thể thêm Trình nhận dạng cử chỉ Long Press từ Thư viện đối tượng giống như bạn thêm các đối tượng khác như UIButtons và UILabels.

nhập mô tả hình ảnh ở đây Ban đầu những gì tôi đã sử dụng là tôi chỉ lấy một

2) Đặt các cửa hàng tham chiếu đến UIButtonvà gửi hành động với Chủ sở hữu tệp.

nhập mô tả hình ảnh ở đây

Lưu ý: Nếu bạn có nhiều UIButton hoặc bất kỳ đối tượng nào khác, bạn sẽ cần nhận dạng cử chỉ riêng cho từng đối tượng. Để biết thêm chi tiết xin vui lòng tham khảo câu hỏi này của tôi. Nhận thẻ UIButton sai trên Trình nhận dạng cử chỉ nhấn dài


Rất dễ dàng để liên kết nhiều hơn một UIView với bộ nhận dạng khách bằng cách sử dụng IB. Câu hỏi là về việc tạo mã.
AlexeyVMP

3

Nếu bạn có chế độ xem cố định, tôi khuyên bạn nên làm một cái gì đó như thế này

[self.view1 addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapTapTap:)]];
[self.view2 addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapTapTap:)]];

cách đó sẽ giảm nhiều biến vô dụng khác nhau


3

Bạn có thể tạo một tiện ích mở rộng chung trên chế độ xem để thêm nhận dạng cử chỉ dễ dàng. Đây chỉ là một ví dụ nhưng nó có thể trông như thế này

extension UIView {

    func setGestureRecognizer<Gesture: UIGestureRecognizer>(of type: Gesture.Type, target: Any, actionSelector: Selector, swipeDirection: UISwipeGestureRecognizer.Direction? = nil, numOfTaps: Int = 1) {
    let getRecognizer = type.init(target: target, action: actionSelector)

    switch getRecognizer {
    case let swipeGesture as UISwipeGestureRecognizer:
        guard let direction = swipeDirection else { return }
        swipeGesture.direction = direction
        self.addGestureRecognizer(swipeGesture)
    case let tapGesture as UITapGestureRecognizer:
        tapGesture.numberOfTapsRequired = numOfTaps
        self.addGestureRecognizer(tapGesture)
    default:
        self.addGestureRecognizer(getRecognizer)
    }
  }

}

Để thêm trình nhận dạng 2 chạm vào chế độ xem, bạn chỉ cần gọi:

let actionSelector = #selector(actionToExecute)
view.setGestureRecognizer(of: UITapGestureRecognizer.self, target: self, actionSelector: actionSelector, numOfTaps: 2)

Bạn cũng có thể dễ dàng thêm một công cụ nhận dạng vuốt

view.setGestureRecognizer(of: UISwipeGestureRecognizer.self, target: self, actionSelector: actionSelector, swipeDirection: .down)

và như thế. Chỉ cần nhớ rằng mục tiêu phải được liên kết với bộ chọn.


2

Ghi đè lớp bằng '<UIScrollViewDelegate> '

Và sử dụng phương thức này trong lớp .m:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
    return YES;
}

Phương pháp này sẽ giúp bạn kích hoạt nhiều thao tác vuốt trên một chế độ xem ..


2

Điều gì về việc viết lại (tạo lại) Gesture của bạn Nhận ra mỗi khi bạn thêm một trình nhận dạng cử chỉ trỏ đến cùng một chức năng. Trong trường hợp dưới đây nó hoạt động. Tôi đang sử dụng IBOutletCollection

Swift 2:

@IBOutlet var topicView: [UIView]!

override func viewDidLoad() {
        for view in self.topicView as [UIView] {
        view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: "viewClicked:"))
    }
}

func viewClicked(recognizer: UITapGestureRecognizer) {
    print("tap")
}

-6

Bạn có thể làm điều đó bằng cách sử dụng mã này các chế độ xem của tôi là số lượt xem hình ảnh trong xib.

- (void)viewDidLoad
{
    firstIV.tag = 501;
    secondIV.tag = 502;
    thirdIV.tag = 503;
    forthIV.tag = 504;

    [self addTapGesturetoImageView: firstIV];
    [self addTapGesturetoImageView: secondIV];
    [self addTapGesturetoImageView: thirdIV];
    [self addTapGesturetoImageView: forthIV];
}

-(void)addTapGesturetoImageView:(UIImageView*)iv
{
    iv.userInteractionEnabled = YES;
    UITapGestureRecognizer * textfielBGIVTapGasture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(textfielBGIVTapped:)];
    textfielBGIVTapGasture.numberOfTapsRequired = 1;
    [iv addGestureRecognizer:textfielBGIVTapGasture];
}

- (void)textfielBGIVTapped:(UITapGestureRecognizer *)recognizer {
    int tag = recognizer.view.tag-500;
    switch (tag) {
        case 1:
        {
            //firstIV tapped;
            break;
        }
        case 2:
        {
            //secondIV tapped;
            break;
        }
        case 3:
        {
            //thirdIV tapped;
            break;
        }
        case 4:
        {
            //forthIV tapped;
            break;
        }
        default: {
            break;
        }
    }
}

1
Bạn đang tạo nhiều nhận dạng cử chỉ; câu hỏi ban đầu của tôi là về việc sử dụng lại một trình nhận dạng cử chỉ, điều mà bạn không thể làm được.
kubi

1
Điểm thêm 500vào tất cả các thẻ của chế độ xem của bạn và sau đó trừ đi là 500gì? Tại sao không chỉ bắt đầu các thẻ của bạn tại 1(hoặc thậm chí 0) thay vì 501?
ma11hew28

@MattDiPasquale, Không quan trọng nếu bạn muốn bắt đầu với 1nó, tôi đã sao chép mã này từ ứng dụng của mình, nơi tôi sẽ đưa nó từ đó 501. Nhưng vâng, đừng cho 0bcoz tôi đã đọc ở đâu đó rằng nó luôn chỉ ra quan điểm của phụ huynh nên nó sẽ tạo ra sự phức tạp, hãy tin tôi, tôi đã đối mặt với nó.
Dilip

Văn bản chính trong tài liệu là "Khung nhìn thiết lập một tham chiếu mạnh mẽ đến bộ nhận dạng cử chỉ." có nghĩa là quan điểm sở hữu cử chỉ. Các cử chỉ chỉ có thể có một chủ sở hữu. Xem liên kết
Phantom59
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.