Ich füge programmgesteuert einen UITapGestureRecognizer zu einer meiner Ansichten hinzu:
let gesture = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(modelObj:myModelObj)))
self.imageView.addGestureRecognizer(gesture)
func handleTap(modelObj: Model) {
// Doing stuff with model object here
}
Das erste Problem, auf das ich gestoßen bin, war "Argument von '#selector' bezieht sich nicht auf eine '@Objc'-Methode, -Eigenschaft oder -Initialisierer.
Cool, also habe ich @objc zur handleTap-Signatur hinzugefügt:
@objc func handleTap(modelObj: Model) {
// Doing stuff with model object here
}
Jetzt erhalte ich die Fehlermeldung "Methode kann nicht als @objc markiert werden, da der Typ des Parameters in Objective-C nicht dargestellt werden kann.
Es ist nur ein Bild der Karte eines Gebäudes, wobei einige Pin-Bilder den Standort von Sonderzielen angeben. Wenn der Benutzer auf einen dieser Pins tippt, möchte ich wissen, auf welchen Punkt von Interesse er getippt hat, und ich habe ein Modellobjekt, das diese Punkte von Interesse beschreibt. Ich verwende dieses Modellobjekt, um dem Pin-Bild die Koordinaten auf der Karte zu geben, sodass ich dachte, es wäre für mich einfach gewesen, das Objekt einfach an den Gestenhandler zu senden.
Antworten:
Es sieht so aus, als ob Sie ein paar Dinge falsch verstehen.
Bei Verwendung von Ziel / Aktion muss die Funktionssignatur eine bestimmte Form haben…
func doSomething(sender: Any)
oder
func doSomething(sender: Any, forEvent event: UIEvent)
wo…
In Ihrem Fall ist der Absender der
UITapGestureRecognizer
Auch
#selector()
sollte die func Signatur enthalten, und NICHT übergebenen Parameter umfassen. So für…func handleTap(sender: UIGestureRecognizer) { }
du solltest haben…
let gesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(sender:)))
Angenommen, die Funktion und die Geste befinden sich in einem Ansichtscontroller, von dem
modelObj
eine Eigenschaft / ein Ivar ist, müssen Sie sie nicht mit dem Gestenerkenner übergeben. Sie können einfach darauf verweisenhandleTap
quelle
userInfo: Any?
Parameter, die in Verbindung mit dieser Lösung verwendet werden können, um Modellobjekte mit dem Absender zu übergeben.Schritt 1: Erstellen Sie das benutzerdefinierte Objekt des Absenders.
Schritt 2: Fügen Sie Eigenschaften hinzu, die Sie ändern möchten, und zwar als benutzerdefiniertes Objekt des Absenders
Schritt 3: Geben Sie den Absender in der Empfangsfunktion in ein benutzerdefiniertes Objekt ein und greifen Sie auf diese Eigenschaften zu
Zum Beispiel: Klicken Sie auf die Schaltfläche, wenn Sie die Zeichenfolge oder ein benutzerdefiniertes Objekt senden möchten
Schritt 1: erstellen
class CustomButton : UIButton { var name : String = "" var customObject : Any? = nil var customObject2 : Any? = nil convenience init(name: String, object: Any) { self.init() self.name = name self.customObject = object } }
Schritt 2-a: Legen Sie die benutzerdefinierte Klasse auch im Storyboard fest
Schritt 2-b: Erstellen Sie das IBOutlet dieser Schaltfläche mit einer benutzerdefinierten Klasse wie folgt
@IBOutlet weak var btnFullRemote: CustomButton!
Schritt 3: Fügen Sie Eigenschaften hinzu, die Sie ändern möchten, und zwar als benutzerdefiniertes Objekt des Absenders
btnFullRemote.name = "Nik" btnFullRemote.customObject = customObject btnFullRemote.customObject2 = customObject2 btnFullRemote.addTarget(self, action: #selector(self.btnFullRemote(_:)), for: .touchUpInside)
Schritt 4: Geben Sie den Absender in der Empfangsfunktion in ein benutzerdefiniertes Objekt ein und greifen Sie auf diese Eigenschaften zu
@objc public func btnFullRemote(_ sender: Any) { var name : String = (sender as! CustomButton).name as? String var customObject : customObject = (sender as! CustomButton).customObject as? customObject var customObject2 : customObject2 = (sender as! CustomButton).customObject2 as? customObject2 }
quelle
Swift 5.0 iOS 13
Ich stimme einer großartigen Antwort von Ninad zu . Hier sind meine 2 Cent, die gleiche und doch andere Technik; eine minimale Version.
Erstellen Sie eine benutzerdefinierte Klasse, werfen Sie eine Aufzählung, um den Code so wartbar wie möglich zu halten.
enum Vs: String { case pulse = "pulse" case precision = "precision" } class customTap: UITapGestureRecognizer { var cutomTag: String? }
Verwenden Sie diese Option, und stellen Sie sicher, dass Sie die benutzerdefinierte Variable in den Balgin setzen. Wenn Sie hier ein einfaches Etikett verwenden, beachten Sie die letzte Zeile. Wichtige Etiketten sind normalerweise nicht interaktiv.
let precisionTap = customTap(target: self, action: #selector(VC.actionB(sender:))) precisionTap.customTag = Vs.precision.rawValue precisionLabel.addGestureRecognizer(precisionTap) precisionLabel.isUserInteractionEnabled = true
Und richten Sie die Aktion damit ein. Beachten Sie, dass ich die reine Aufzählung verwenden wollte, diese jedoch von Objective C nicht unterstützt wird. Daher verwenden wir einen Basistyp, in diesem Fall String.
@objc func actionB(sender: Any) { // important to cast your sender to your cuatom class so you can extract your special setting. let tag = customTag as? customTap switch tag?.sender { case Vs.pulse.rawValue: // code case Vs.precision.rawValue: // code default: break } }
Und da hast du es.
quelle
Erstellen Sie einfach eine benutzerdefinierte Klasse von UITapGestureRecognizer =>
import UIKit class OtherUserProfileTapGestureRecognizer: UITapGestureRecognizer { let userModel: OtherUserModel init(target: AnyObject, action: Selector, userModel: OtherUserModel) { self.userModel = userModel super.init(target: target, action: action) } }
Und dann erstellen Sie die UIImageView-Erweiterung =>
import UIKit extension UIImageView { func gotoOtherUserProfile(otherUserModel: OtherUserModel) { isUserInteractionEnabled = true let gestureRecognizer = OtherUserProfileTapGestureRecognizer(target: self, action: #selector(self.didTapOtherUserImage(_:)), otherUserModel: otherUserModel) addGestureRecognizer(gestureRecognizer) } @objc internal func didTapOtherUserImage(_ recognizer: OtherUserProfileTapGestureRecognizer) { Router.shared.gotoOtherUserProfile(otherUserModel: recognizer.otherUserModel) } }
Verwenden Sie es jetzt wie =>
self.userImageView.gotoOtherUserProfile(otherUserModel: OtherUserModel)
quelle
Das mag eine schreckliche Praxis sein, aber ich füge einfach hinzu, was ich wiederherstellen möchte
button.restorationIdentifier = urlString
und
@objc func openRelatedFact(_ sender: Any) { if let button = sender as? UIButton, let stringURL = factButton.restorationIdentifier, let url = URL(string: stringURL) { if UIApplication.shared.canOpenURL(url) { UIApplication.shared.open(url, options: [:]) } } }
quelle
cell.btn.tag = indexPath.row //setting tag cell.btn.addTarget(self, action: #selector(showAlert(_ :)), for: .touchUpInside) @objc func showAlert(_ sender: UIButton){ print("sender.tag is : \(sender.tag)")// getting tag's value }
quelle