Birden çok görünüme UIGestureRecognizer ekleyebilir misiniz?


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

Yukarıdaki kodda sadece açık muslukları view2tanınır. Üçüncü satırı yorumlarsam o zaman musluklar view1tanınır. Haklıysam ve yalnızca bir kez jest tanıtıcısı kullanabiliyorsanız, bunun bir hata olup olmadığından emin değilim veya sadece biraz daha dokümantasyona ihtiyacı var.

Yanıtlar:


334

A UIGestureRecognizer, tek bir görünümle kullanılmalıdır. Belgelerin sivilceli olduğunu kabul ediyorum. Yani UIGestureRecognizertek sahiptir viewözellik onu ele veriyor:

görünüm

Hareket algılayıcının bağlı olduğu görünüm. (Sadece oku)

@property (anatomik olmayan, salt okunur) UIView * görünümü

Tartışma addGestureRecognizer: yöntemini kullanarak bir UIView nesnesine bir hareket tanıyıcı eklersiniz (veya eklersiniz).


11
Çünkü bir görünüme hareket tanıyıcı eklemek çalışma zamanında gerçekleşir (derleme zamanı ile karşılaştırıldığında).
TomSwift

1
Bunu anladım, ancak bir değişkeni kullanmadığımızı tespit etmek gibi, XCode, aynı tanıyıcıyı birden çok görünüme geçirdiğimizi ve kodlayıcıyı uyarabildiğini söyleyebilir.
Zoltán Matók

1
Aynı UITapGestureRecognizer'ı atayan birden çok görünüm hakkındaki derleyici uyarısı saçmadır, çünkü bunu örneğin örneğin dokunma hareketi tanıyıcıyı bir görünümden diğerine taşımak istiyorsanız bunu bilerek yapmak isteyebilirsiniz. Bununla birlikte, hareket tanıma cihazının birden çok görünümde kullanılamaması saçma bir sınırlamadır.
Erik van der Neut

1
iOS 9 artık hareket tanıtıcı başına tek bir görünüm uyguluyor, aşağıdaki arayüz oluşturucu yöntemini kullanıyordum, ancak şimdi kullanmaya çalıştığımda (kısalık için kesilen bazı ayrıntılar) aşağıdaki mesajı alıyorum: UYARI: Bir Hareket tanıyıcı (< UITapGestureRecognizer: .....>), birden fazla görünüme eklenecek bir storyboard / xib içinde ayarlandı (-> <UIView:; frame = (0 44; 600 536); autoresize = RM + BM; gestureRecognizers = < NSArray ...:>; layer = <CALayer: ... >>) bir seferde buna asla izin verilmedi ve şimdi uygulanıyor. İOS 9.0'dan başlayarak, yüklendiği ilk görünüme yerleştirilir.
George Brown

İkinci kez görünüme ekliyorsanız, görünüm bu tanıyıcı tarafından otomatik olarak eklenmeden önce eklenmiştir UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didPressed:)]; [self.view1 addGestureRecognizer:tapRecognizer]; [self.view2 addGestureRecognizer:tapRecognizer];Çıktı görünümü1'in hareket tanıyıcı dizisi yoktur;
view2'de

48

Aşağıdakileri kullanarak etrafta dolaştım.

for (UIButton *aButton in myButtons) {

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

}

Daha sonra handleLongPress yönteminde, jest tanıtıcısının görünümüne eşit bir UIButton ayarladım ve bu düğmeye dayanarak yaptığım işi

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

1
Harika cevap. Bir ton teşekkürler. "Birden çok görünüme UIGestureRecognizer nasıl eklenir?" Sorusu bu kabul edilmiş cevap olabilirdi.
D_D

7
Bu (ya da buna çok yakın bir şey) benim için işe yaramadı. Arayüz Oluşturucu'da bir dokunma hareketi tanıyıcıya birkaç görünüm ekledim ve tanıyıcıyı bir eyleme bağladım. Ekli bir görünüme dokunulduğunda eylem çağrıldı, ancak gesture.view her zaman eklenen son görünümdü.
Aneil Mallavarapu

Bu gerçekten güzel bir cevap ve aynı zamanda gerçekten yararlı ve @MicRO +1
Dilip ile

2
Aneil, çünkü hareket tanıma cihazının yeni örneklerini oluşturmadınız. Bu yanıttaki döngüde olanlar, her biri yalnızca bir görünüm eklenmiş yeni hareket tanıyıcı örneklerinin oluşturulduğudur. Hepsi aynı işleyiciyi gösterebilir, burada hangisine dokunulduğunu görmek için görünümü kontrol edebilirsiniz.
Erik van der Neut

1
Birisi bunun artık Obj-C / Swift'in mevcut sürümünde çalışmadığını doğrulayabilir mi?
Maxi Mus

18

Swift 3 için herkesin buna ihtiyacı varsa: Yukarıdaki Bhavik Rathod Yanıtı'na dayanarak.

 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
temel olarak iki görünüm için birden fazla hareket yaratıyor, yine de aynı kural: her hareketin tek bir görünümü var
Abdoelrhman

3
Hayır, işlev her çağrıldığında bir jest yaratır
Abdoelrhman

2
işlevin adı yanlış. buradaki mantıksal fonksiyon bir alma fonksiyonudur. bu yüzden adlandırılmalıdır: getGestureRecognizeçünkü bu işlev böyle yapar
David Seek

Benim için iyi çalış! Ve birden çok değişken oluşturmaktan veya kod oluşturmak için tüm kodu koymaktan daha temiz kod addGestureRecognizer
Codenator81

11

Böyle bir şey yapabiliriz, bu kolay ve basit

1) kumandanızda aşağıdaki gibi bir işlev oluşturun (bu işlev GestureRecognizer döndürecektir)

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

2) şimdi bu tanıyıcıyı birden çok görünümde ayarlayın

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

Görünümler yerine iki etiket kullandığımda benim için çalışmıyor.
Mihir Oza

3
@Mihir Oza, doğrudan UILabels için çalışamaz. Etiketler nedeniyle kullanıcı etkileşimi için bir anlamı yoktur. UILabels için hareketler eklemek istiyorsanız, Swift'e bu tek satırlı labelName..isUserInteractionEnabled = true değerini ekleyin . Ardından hareketleri ekleyin.
iOS

Çok geç adamım, bunu zaten düzelttim. Ama öneri için teşekkürler. Yorumunuz yığın kullanıcıları için faydalı olacaktır. Takdir!
Mihir Oza

1
Sanırım hat setNumberOfTapsRequired:1gerekli değil
Naveed Abbas

9

Hayır, hareket tanıyıcıları birden fazla görünüme eklememelisiniz.

Apple belgelerinde bu açık bilgiler var:

Hareket Tanıyıcılar Bir Görünüme Eklenir

Her hareket tanıyıcı bir görünümle ilişkilendirilir. Buna karşılık, bir görünüm birden çok hareket tanıyıcıya sahip olabilir, çünkü tek bir görünüm birçok farklı harekete yanıt verebilir. Bir hareket tanıyıcının belirli bir görünümde meydana gelen dokunuşları tanıması için hareket tanıyıcıyı o görünüme eklemeniz gerekir.

İOS için Olay İşleme Kılavuzu - Hareket Tanıyıcılar Apple Geliştirici Kitaplığı

Diğerlerinin de belirttiği gibi, bazı durumlarda çalışabilirler, açıkça belgelere aykırıdır ve gelecekteki iOS sürümlerinde değişebilir.

Yapabileceğiniz şey, izlemek istediğiniz görünümlere ayrı hareket tanıyanları eklemektir ve bunlar ortak bir işlemi paylaşabilir.


4

Birisi kwalker gibi birden fazla düğme için jest görünümü eklemek için kodlamak istemiyorsa ve bunu Interface Builder ile yapmak istiyorsanız, bu size yardımcı olabilir.

1) UIButtons ve UILabels gibi diğer nesneleri eklediğiniz gibi Nesne Kitaplığından Long Press hareket Tanıyıcı ekleyebilirsiniz.

resim açıklamasını buraya girin Başlangıçta kullandığım sadece bir tane aldım

2) UIButtonDosya Sahibine referans çıkışları ayarlayın ve eylemler gönderin .

resim açıklamasını buraya girin

Not: Birden fazla UIButton'unuz veya başka bir nesneniz varsa, bunların her biri için ayrı bir hareket tanımlayıcıya ihtiyacınız olacaktır. Daha fazla ayrıntı için lütfen bu soruma bakın. Uzun basın jest tanıyıcıda yanlış UIButton etiketi alma


IB kullanarak misafir tanıyıcıya birden fazla UIView bağlamak çok kolaydır. Soru kod üretimi ile ilgiliydi.
AlexeyVMP

3

Sabit görüşünüz varsa böyle bir şey yapmanızı öneririm

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

bu şekilde birden fazla farklı yararsız değişken azalır


3

Hareket algılayıcıları kolayca eklemek için görünümde genel bir uzantı oluşturabilirsiniz. Bu sadece bir örnek ama şöyle görünebilir

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

}

Bir görünüme 2 musluk tanıyıcı eklemek için şunu aramanız yeterlidir:

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

Kaydırma algılayıcıyı da kolayca ekleyebilirsiniz

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

ve bunun gibi. Hedefin seçiciye bağlı olması gerektiğini unutmayın.


2

Sınıfı ' <UIScrollViewDelegate>' geçersiz kıl

Ve bu yöntemi .m sınıfında kullanın:

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

Bu yöntem, tek bir görünümde birden çok hızlıca kaydırmayı etkinleştirmenize yardımcı olur.


2

Aynı işleve işaret eden bir jest tanıyıcıyı her eklediğinizde Hareketinizi yeniden yazın (yeniden oluşturun). Aşağıdaki durumda çalışır. IBOutletCollection kullanıyorum

Hızlı 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

Bu kodu kullanarak, xib'deki görüntülemelerim görünümlerimi yapabilirsiniz.

- (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
Birden çok hareket tanıyıcı oluşturuyorsunuz; asıl sorum, yapamayacağınız tek bir hareket tanıyıcıyı tekrar kullanmaktı.
Kubi

1
500Tüm görünümlerinizin etiketlerine eklemenin ve ardından çıkartmanın anlamı nedir 500? Neden etiketlerinizi sadece yerine ( 1hatta çift 0) başlatmıyorsunuz 501?
ma11hew28

@MattDiPasquale, onunla başlamak istiyorsanız önemli değil 1onun sadece ben onu veriyorum benim app bu kodu kopyaladık 501. Ama evet 0bcoz vermeyin bir yerde okudum her zaman onun ebeveyn-görüş göstermek bu yüzden komplikasyon yaratacak, inan bana karşı karşıya.
Dilip

Belgelerdeki anahtar metin "Görünüm, hareket tanıyıcıya güçlü bir referans oluşturur." bu da görünümün jestin sahibi olduğu anlamına gelir. Hareketin yalnızca bir sahibi olabilir. Bkz. Bağlantı
Phantom59
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.