UIGestureRecognizer를 여러보기에 연결할 수 있습니까?


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

위의 코드에서는 탭만 view2인식됩니다. 세 번째 줄을 주석 처리하면 탭 view1이 인식됩니다. 내가 옳고 제스처 인식기를 한 번만 사용할 수 있다면 이것이 버그인지 확실하지 않거나 더 많은 문서가 필요합니다.

답변:


334

A UIGestureRecognizer는 단일 뷰와 함께 사용됩니다. 문서가 드물다는 데 동의합니다. 그것은 UIGestureRecognizer하나의 view속성을 가지고 있습니다 :

전망

제스처 인식기가 연결된보기입니다. (읽기 전용)

@property (비 원자, 읽기 전용) UIView * view

토론 addGestureRecognizer : 메소드를 사용하여 제스처 인식기를 UIView 객체에 첨부 (또는 추가)합니다.


11
뷰에 제스처 인식기를 추가하면 런타임 (컴파일 시간 대비)에 발생합니다.
TomSwift

1
나는 그것을 얻었지만 변수를 사용하지 않았다는 것을 감지하는 것과 마찬가지로 XCode는 코드를 기반으로 동일한 인식기를 여러 뷰에 전달하고 코더에게 경고 할 수 있음을 알 수 있습니다.
Zoltán Matók

1
동일한 UITapGestureRecognizer를 할당하는 여러 뷰에 대한 컴파일러 경고는 의미가 없습니다. 예를 들어 탭 제스처 인식기를 한 뷰에서 다른 뷰로 이동하려는 경우 의도적으로이 작업을 수행 할 수 있기 때문입니다. 즉, 제스처 인식기를 여러보기에서 사용할 수 없다는 것은 어리석은 한계입니다.
Erik van der Neut

1
iOS 9는 이제 제스처 인식기 당 단일보기를 시행하고 아래 인터페이스 작성기 방법을 사용하고 있지만 사용하려고하면 다음 메시지가 표시됩니다 (일부 세부 정보는 간략하게 잘라 내기). 경고 : 제스처 인식기 (< UITapGestureRecognizer : .....>)가 스토리 보드 / xib에 설정되어 둘 이상의보기에 추가되었습니다 (-> <UIView :; frame = (0 44; 600 536); 자동 크기 조정 = RM + BM; gestureRecognizers = < NSArray ... :>; layer = <CALayer : ... >>) 한 번에 허용되지 않았으며 이제 적용됩니다. iOS 9.0부터는로드 된 첫 번째보기에 배치됩니다.
George Brown

두 번째로보기에 추가하는 경우이 인식기에 의해보기가 자동으로 연결 해제되기 전에보기가 첨부되었습니다. UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didPressed:)]; [self.view1 addGestureRecognizer:tapRecognizer]; [self.view2 addGestureRecognizer:tapRecognizer];출력 view1에는 제스처 인식기 배열이 없습니다. view2 제스처 인식기 배열을 가지고
kokos8998

48

아래를 사용하여 문제를 해결했습니다.

for (UIButton *aButton in myButtons) {

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

}

그런 다음 handleLongPress 메서드에서 제스처 인식기의 뷰와 동일한 UIButton을 설정하고 해당 버튼을 기반으로 수행하는 작업을 분기합니다.

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

1
좋은 답변입니다. 질문이 "여러 뷰에 UIGestureRecognizer를 어떻게 연결합니까?"
D_D

7
이것 (또는 이것에 매우 가까운 것)은 나를 위해 작동하지 않았습니다. Interface Builder에서 탭 제스처 인식기에 몇 가지보기를 추가하고 인식기를 동작에 연결했습니다. 첨부 된보기를 탭할 때마다 조치가 호출되었지만 gesture.view는 항상 마지막으로 첨부 된보기였습니다.
Aneil Mallavarapu

이것은 정말 좋은 답변이며 정말 도움이되며 @MicRO +1에 동의합니다.
Dilip

2
아 네일, 제스처 인식기의 새 인스턴스를 만들지 않았기 때문입니다. 이 답변의 루프에서 일어나는 것은 각각 하나의 뷰가 첨부 된 새로운 제스처 인식기 인스턴스가 생성된다는 것입니다. 그들은 모두 같은 핸들러를 가리킬 수 있으며, 어떤 핸들러가 터치되었는지보기를 확인합니다.
Erik van der Neut

1
다른 사람이 현재 버전의 Obj-C / Swift에서 더 이상 작동하지 않음을 확인할 수 있습니까?
맥시 머스

18

누군가가 이것을 요구하는 경우 Swift 3의 경우 : 위의 Bhavik Rathod Answer에 근거합니다.

 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
기본적으로 두보기에 대해 여러 제스처를 작성하지만 여전히 동일한 규칙입니다. 모든 제스처에는 하나의보기 만 첨부해야합니다.
Abdoelrhman

3
아니요,이 함수는 호출 될 때마다 제스처를 만듭니다
Abdoelrhman

2
함수 이름이 잘못되었습니다. 여기서 논리 함수는 함수입니다. 이름을 지정해야합니다. getGestureRecognize이것이
David Seek

나를 위해 일하세요! addGestureRecognizer
Codenator81

11

우리는 무언가를 할 수 있습니다. 이렇게 쉽고 간단합니다

1) 컨트롤러에서 아래와 같이 함수를 만듭니다 (이 함수는 GestureRecognizer를 반환합니다)

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

2) 이제이 인식기를 여러보기로 설정하십시오.

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

뷰 대신 두 개의 레이블을 사용하면 작동하지 않습니다.
Mihir Oza

3
@Mihir Oza, UILabels에서 직접 작동 할 수 없습니다. 라벨 때문에 사용자 상호 작용에는 의미가 없습니다. UILabels에 제스처를 추가하려면 Swift 에서이 단일 행 labelName..isUserInteractionEnabled = true 를 추가하십시오 . 그런 다음 제스처를 추가하십시오.
iOS

너무 늦었 어, 나는 이미 그것을 고쳤다. 그러나 제안에 감사드립니다. 귀하의 의견은 스택 사용자에게 도움이 될 것입니다. 감사합니다!
Mihir Oza

1
나는 라인 setNumberOfTapsRequired:1이 필요하지 않은 것 같아요
Naveed Abbas

9

아니오. 제스처 인식기를 둘 이상의보기에 첨부해서는 안됩니다.

Apple 문서에는 다음과 같은 명시적인 정보가 있습니다.

제스처 인식기가 뷰에 연결됩니다

모든 제스처 인식기는 하나의 뷰와 연결됩니다. 반대로, 하나의보기가 여러 가지 다른 제스처에 응답 할 수 있으므로보기에는 여러 개의 제스처 인식기가있을 수 있습니다. 제스처 인식기가 특정보기에서 발생하는 터치를 인식하려면 제스처 인식기를 해당보기에 연결해야합니다.

iOS 용 이벤트 처리 안내서-제스처 인식기 Apple Developer Library

다른 사람들이 언급했듯이 그들은 경우에 따라 작동 할 수 있지만 문서와 분명히 반대이며 향후 iOS 버전에서 변경 될 수 있습니다.

수행 할 수있는 작업은 모니터링하려는보기에 별도의 제스처 인식기를 추가하고 공통 동작을 공유 할 수 있다는 것입니다.


4

kwalker 와 같은 여러 버튼에 대한 제스처보기를 추가하기 위해 코드를 작성하지 않으려면 Interface Builder를 통해 수행하려는 경우 도움이 될 수 있습니다.

1) UIButton 및 UILabels와 같은 다른 객체를 추가하는 것처럼 객체 라이브러리에서 Long Press 제스처 인식기를 추가 할 수 있습니다.

여기에 이미지 설명을 입력하십시오 처음에 내가 사용한 것은 하나만 가져갔습니다.

2) 참조 아웃렛을 설정 UIButton하고 파일 소유자와 조치를 보냄.

여기에 이미지 설명을 입력하십시오

참고 : UIButton 또는 다른 객체가 여러 개인 경우 각각에 대해 별도의 제스처 인식기가 필요합니다. 자세한 내용은이 질문을 참조하십시오. 길게 누르기 제스처 인식기에서 잘못된 UIButton 태그 가져 오기


IB를 사용하여 둘 이상의 UIView를 게스트 인식기에 바인딩하는 것은 매우 쉽습니다. 문제는 코드 생성에 관한 것이었다.
AlexeyVMP

3

당신이 고정보기를 가지고 있다면 나는 당신이 이와 같은 일을 할 것을 제안합니다

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

그렇게하면 여러 가지 다른 쓸모없는 변수가 줄어 듭니다.


3

제스처 인식기를 쉽게 추가하기 위해 뷰에서 일반 확장을 만들 수 있습니다. 이것은 단지 예일 뿐이지 만 다음과 같이 보일 수 있습니다

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)
    }
  }

}

뷰에 2 탭 인식기를 추가하려면 전화하십시오.

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

스 와이프 인식기를 쉽게 추가 할 수도 있습니다.

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

등등. 대상은 선택기에 연결되어 있어야합니다.


2

' <UIScrollViewDelegate>'로 클래스 재정 의

그리고 .m 클래스 에서이 방법을 사용하십시오 :

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

이 방법을 사용하면 단일보기에서 여러 번 스 와이프 할 수 있습니다.


2

동일한 기능을 가리키는 제스처 인식기를 추가 할 때마다 GestureRecognize를 다시 작성 (재 작성)하는 방법은 무엇입니까? 아래의 경우 작동합니다. IBOutletCollection을 사용하고 있습니다

스위프트 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

이 코드를 사용하여 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
여러 동작 인식기를 작성하고 있습니다. 내 원래의 질문은 당신이 할 수없는 단일 제스처 인식기를 재사용하는 것입니다.
kubi

1
500모든 조회수 태그 에 더한 다음 빼는 요점은 무엇입니까 500? 왜 단지에 태그를 시작하지 1(또는 0) 대신 501?
ma11hew28

@MattDiPasquale, 당신이 1그것 으로 시작하고 싶을지라도 중요하지 않습니다 . 내가 그것을주는 응용 프로그램 에서이 코드를 복사했습니다 501. 그러나 그렇습니다 0.bcoz 에게 어딘가 읽었을 때 항상 부모보기를 나타내므로 합병증이 생길 것입니다.
Dilip

설명서의 핵심 텍스트는 "보기는 제스처 인식기에 대한 강력한 참조를 설정합니다."입니다. 뷰가 제스처를 소유하고 있음을 의미합니다. 제스처는 한 명의 소유자 만 가질 수 있습니다. 링크
Phantom59
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.