2017-05-24 6 views
2

So habe ich ein Bild in meiner App, die ich in Xcode schnell erstellen erstellt und ich möchte zum Beispiel "Image Clicked" drucken, wenn das Bild angetippt wird. Hier ist, was ich habe:Swift 3 Überprüfen, wenn der Benutzer auf das Bild klickt

Diese Funktion ist, die annehmen, heißt zu erhalten, wenn Benutzer das Bild tippen:

func imageViewTapped(imageView: UIImageView) { 
    print("Image Clicked") 
} 

Ich habe diese Funktion, die die Interaktion des Benutzers mit dem Bild ergänzt:

func tapRecognition(image: UIImageView) { 
    image.isUserInteractionEnabled = true 
    let tapRecognizer = UITapGestureRecognizer(target: self, action: Selector(("imageViewTapped:"))) 
    image.addGestureRecognizer(tapRecognizer) 
} 

und last but not least habe ich ein Bild vom Typ UIImageView in meiner viewDidLoad (Funktion) und ich rief:

tapRecognition(image: imageView) 

Wenn ich dies ausführen und auf das Bild klicken, bekomme ich einen Fehler, der besagt: "Beenden mit nicht abgefangener Ausnahme vom Typ NSException". Jede Hilfe wäre großartig! Danke vielmals.

+0

Wo wird 'imageView' initialisiert? –

+1

Sofern Sie nicht den alten Swift verwenden, müssen Sie die korrekte Auswahlsyntax verwenden und den korrekten Methodennamen im Selektor angeben. – rmaddy

+1

Haben Sie IBOutlet richtig angeschlossen, kann dies zu NSException führen –

Antwort

5

Hier einige Code ist die Swift 3 unter Verwendung funktioniert:

override func viewDidLoad() { 
    super.viewDidLoad() 

    // #1 
    let myImage = UIImage(named: "myImage") 
    let imageView = UIImageView() 
    imageView.image = myImage 

    // #2 
    imageView.isUserInteractionEnabled = true 
    let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageTapped)) 
    imageView.addGestureRecognizer(tapRecognizer) 

    // #3 
    imageView.translatesAutoresizingMaskIntoConstraints = false 
    view.addSubview(imageView) 
    // set imageView contraints 

} 

// #4 
func imageTapped(recognizer: UITapGestureRecognizer) { 
    print("Image was tapped") 
    let thePoint = recognizer.location(in: view) 
    let theView = recognizer.view 
} 
  • 1 Während Sie Code ein bisschen anders ist und einige fehlen, Ich glaube, das ist im Grunde das Gleiche. Sofern Sie nicht anderweitig auf image oder imageView zugreifen müssen, deklarieren Sie sie lokal in viewDidLoad. (Ich würde vorschlagen, keine UIImageView Benennung wie Sie (image), wie die anderen verwirrend sein kann Ihren Code zu lesen.)

  • 2 Hier ist, wo ich denke, @rmaddy korrekt ist. Wenn Sie Swift 3 verwenden, ist die richtige Syntax für Selektor, was ich habe. Dies kann das einzige Problem mit unserem Code sein - und ein großes Lob daran, dass ein UIImageView einen Standardwert von isUserInteractioEnabled = true hat.

  • 3 Sie haben keinen Code für das tatsächliche Layout. Wenn Sie jedoch Auto-Layout (im Gegensatz zu Frames) verwenden, wird die Autoresizing-Funktion deaktiviert. Stellen Sie sicher, dass Sie die Ansicht in die Ansichtshierarchie einfügen, und legen Sie die Einschränkungen fest. Viele Male (am gleichmäßigsten) können Sie sie in viewDidLoad setzen, aber wenn Sie brauchen Rahmeninformationen, verwenden Sie entweder viewWillLayoutSubviews oder viewDidLayoutSubviews.

  • 4 Zuerst dachte ich, Ihre Tippfunktion sei in Ordnung, aber bei weiterer Überprüfung ist es nicht so. Der Absender ist nicht die Ansicht, auf die geklopft wurde, es ist der Erkenner. Ich habe nach der print-Anweisung zwei Zeilen Code hinzugefügt. Der erste setzt den CGPoint des Tap in eine Variable. Der zweite setzt den UIView, der an den Erkenner (in diesem Fall imageView) angehängt ist, in eine Variable. Wenn Sie wissen möchten, dass sich eine Unteransicht von imageView im Bereich des Gewindebohrers befindet, verwenden Sie die Methode hitTest().

EDIT:

Ich wurde gefragt, wie die Ansicht zu verwenden (in meinem Beispiel imageView) in der Funktion, die auf dem Hahn ausführt.

Erstens, die eine Sache, die Sie nicht tun können, ist es als Parameter übergeben. Sowohl iOS als auch MacOS funktionieren mit ihren Aktionen nicht so. Aber Sie haben (mindestens) drei Optionen zur Verfügung. (Keiner von ihnen die Tag-Eigenschaft verwenden, die in einigen Szenarien ist eine weitere Option.)

  • 1 Der Code, den Sie gezeigt haben sagen Sie bereits wissen um das Bild nach Ansicht abgehört wurde. Dies ist ein wahrscheinlicher Fall, da jede Geste, die Sie erstellen, nur einer einzelnen Ansicht zugeordnet werden kann. Wenn dies Ihr Szenario ist, sollten Sie Ihre Bildansicht auf der Ebene des Ansichtscontrollers deklarieren und nur das kodieren, was Sie in Ihrer Funktion benötigen.

  • 2 Aber was, wenn Sie zwei Bildansichten in Ihrem View-Controller haben, beide mit einer Tap-Geste verbunden, und Sie möchten, dass sie etwas tun, je nachdem, was angezapft wurde? In diesem Fall können Sie die Eigenschaft view der Geste mit Casting verwenden. Der Skeleton-Code:

    let imageView1 = UIImageView() 
    let imageView2 = UIImageView() 
    let tapRecognizer1 = UITapGestureRecognizer(target: self, action: #selector(imageTapped)) 
    imageView1.addGestureRecognizer(tapRecognizer1) 
    let tapRecognizer2 = UITapGestureRecognizer(target: self, action: #selector(imageTapped)) 
    imageView2.addGestureRecognizer(tapRecognizer2) 
    
    
    func imageTapped(recognizer: UITapGestureRecognizer) { 
        print("Image was tapped") 
        let imageView = recognizer.view as? UIImageView 
        if imageView != nil { 
         //do something here 
        } 
    } 
    

    Beachten Sie, dass das Skelett möglicherweise einen Syntaxfehler im Casting aufweist. Die Logik ist solide, ich schreibe das online, nicht in Xcode. Im Grunde wird die angehängte UIView als Bildansicht gecastet und auf Null überprüft.

  • 3 Der Fall, den ich normalerweise verwende, wenn Sie mehrere Unteransichten haben und Sie wissen möchten, welcher angezapft wurde. In Ihrem Fall, angenommen, Sie hatten zwei UIImageViews wie oben, aber Sie haben die Tap-Erkennung an die Hauptansicht angeschlossen? In diesem Fall können Sie die Methode hitTest() verwenden. Skeleton-Code:

    let imageView1 = UIImageView() 
    let imageView2 = UIImageView() 
    let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageTapped)) 
    imageView1.addGestureRecognizer(self.view) 
    
    func imageTapped(recognizer: UITapGestureRecognizer) { 
        print("Image was tapped") 
        let p = recognizer.location(in: view) 
        if imageView1.layer.hitTest(p) != nil { 
         // do something here to imageView1 
        } else if imageView2.layer.hitTest(p) != nil { 
         // do something here to imageView2 
        } 
    } 
    

    Ich ziehe Schichten zu verwenden, aber Ansichten haben eine hitTest() Methode auch. Der Wert dafür ist eine Ansicht mit 7 Unteransichten, die mit einer einzigen Geste codiert werden können. Wenn Sie möchten, dass Sie auf 3 dieser Unteransichten tippen (und auf die Hauptansicht tippen), können Sie das tun.

    Bezug auf die letzte, ich hatte ein kleines Beispielprojekt für eine Weile. Es enthält eine Bildansicht mit zwei farbigen Beschriftungen als Unteransichten. Wenn eines der Labels angetippt wird, wird ein Zähler inkrementiert. Ich habe dies in 1-2 meiner Antworten verwendet und dachte, ich würde es in ein GitHub-Repository legen. Fühlen Sie sich frei, es zu betrachten: Image with Labels.

+0

Was ist, wenn ich möchte, dass die Funktion imageTapped ein Bild als Parameter nimmt, weil ich etwas mit dem Bild tun will, wenn es angetippt wird ... Ich bekomme, dass diese Frage nur gesagt, etwas zu drucken, wenn das Bild angezapft wird, aber was ist, wenn ich möchte etwas zu einem Bild machen. – tee

+1

Sie können einen Parameter wie diesen nicht übergeben. Aber hier, was Sie tun können - (1) verwenden Sie eine Ansicht/Layer 'hitTest()' Methode, wenn Sie herausfinden müssen, ob es angezapft wurde. Ich füge meiner Antwort ein bisschen mehr Code hinzu. (2) Wenn Sie * bereits * wissen, dass das 'UIImageView' angetippt wurde - was Sie mit dem Code tun können, den Sie angezeigt haben - dann deklarieren Sie' UIImageView' globaler und innerhalb Ihrer Funktion tun Sie, was benötigt wird. – dfd

+0

Ich habe 30 Minuten gebraucht, um den Schnitt zu schreiben, sorry. Aber ich habe drei Optionen erklärt, zwei mit Skelett-Code. Ich habe auch ein kleines Swift 3 Xcode-Projekt zu einem GitHub-Repository hinzugefügt. Hoffe das hilft dir aus! – dfd

0

ändern param Typ wie folgt:

func imageViewTapped(imageView:UITapGestureRecognizer? = nil) { 
    print("Image Clicked") 
} 
+0

Ihre Unterschrift ist nicht leicht verstanden. Wenn die Funktion ausgeführt wird, ist es ** weil ** der Absender - ein UITapGestureRecognizer - ** nicht ** nil ist! Dennoch deklarieren Sie die "Geste" als eine Variable namens "imageView"? Wiederum nicht leicht zu verstehen. – dfd

Verwandte Themen