@selector () in Swift?

660

Ich versuche , eine zu schaffen , NSTimerin Swiftaber ich einige Probleme haben.

NSTimer(timeInterval: 1, target: self, selector: test(), userInfo: nil, repeats: true)

test() ist eine Funktion in derselben Klasse.


Ich erhalte eine Fehlermeldung im Editor:

Es wurde keine Überladung für 'init' gefunden, die die angegebenen Argumente akzeptiert

Wenn ich selector: test()zum selector: nilFehler wechsle , verschwindet er.

Ich habe es versucht:

  • selector: test()
  • selector: test
  • selector: Selector(test())

Aber nichts funktioniert und ich kann in den Referenzen keine Lösung finden.

Arbitur
quelle
11
selector: test()würde testden Rückgabewert aufrufen und an das selectorArgument übergeben.
Michael Dorst

Antworten:

930

Swift selbst verwendet keine Selektoren - mehrere Entwurfsmuster, die in Objective-C Selektoren verwenden, funktionieren in Swift unterschiedlich. (Verwenden Sie beispielsweise die optionale Verkettung für Protokolltypen oder is/ as-tests anstelle von respondsToSelector:und verwenden Sie Verschlüsse, wo immer Sie können, anstatt performSelector:für eine bessere Typ- / Speichersicherheit.)

Es gibt jedoch noch eine Reihe wichtiger ObjC-basierter APIs, die Selektoren verwenden, einschließlich Timer und des Ziel- / Aktionsmusters. Swift bietet den SelectorTyp für die Arbeit mit diesen. (Swift verwendet dies automatisch anstelle des SELTyps von ObjC .)

In Swift 2.2 (Xcode 7.3) und höher (einschließlich Swift 3 / Xcode 8 und Swift 4 / Xcode 9):

SelectorMit dem #selectorAusdruck können Sie einen aus einem Swift-Funktionstyp erstellen.

let timer = Timer(timeInterval: 1, target: object,
                  selector: #selector(MyClass.test),
                  userInfo: nil, repeats: false)
button.addTarget(object, action: #selector(MyClass.buttonTapped),
                 for: .touchUpInside)
view.perform(#selector(UIView.insertSubview(_:aboveSubview:)),
             with: button, with: otherButton)

Das Tolle an diesem Ansatz? Eine Funktionsreferenz wird vom Swift-Compiler überprüft, sodass Sie den #selectorAusdruck nur mit tatsächlich vorhandenen Klassen- / Methodenpaaren verwenden können, die als Selektoren verwendet werden können (siehe "Verfügbarkeit der Selektoren" weiter unten). Sie können Ihre Funktionsreferenz auch nur so spezifisch gestalten, wie Sie es benötigen, gemäß den Swift 2.2+ -Regeln für die Benennung von Funktionstypen .

(Dies ist tatsächlich eine Verbesserung gegenüber der @selector()Direktive von ObjC , da die -Wundeclared-selectorÜberprüfung des Compilers nur überprüft, ob der benannte Selektor vorhanden ist. Die Swift-Funktionsreferenz, die Sie übergeben, um die #selectorExistenz, die Zugehörigkeit zu einer Klasse und die Typensignatur zu überprüfen.)

Es gibt einige zusätzliche Einschränkungen für die Funktionsreferenzen, die Sie an den #selectorAusdruck übergeben:

  • Mehrere Funktionen mit demselben Basisnamen können anhand ihrer Parameterbezeichnungen unter Verwendung der oben genannten Syntax für Funktionsreferenzen (z . B. insertSubview(_:at:)vs insertSubview(_:aboveSubview:)) unterschieden werden. Wenn eine Funktion jedoch keine Parameter hat, besteht die einzige Möglichkeit, sie zu unterscheiden, darin, eine asUmwandlung mit der Typensignatur der Funktion (z . B. foo as () -> ()vs foo(_:)) zu verwenden.
  • In Swift 3.0+ gibt es eine spezielle Syntax für Property Getter / Setter-Paare. Wenn Sie beispielsweise a angeben var foo: Int, können Sie #selector(getter: MyClass.foo)oder verwenden #selector(setter: MyClass.foo).

Allgemeine Hinweise:

Fälle, in denen #selectordies nicht funktioniert, und Benennung: Manchmal haben Sie keine Funktionsreferenz, mit der Sie einen Selektor erstellen können (z. B. mit Methoden, die dynamisch in der ObjC-Laufzeit registriert sind). In diesem Fall können Sie eine Selectoraus einer Zeichenfolge erstellen: z. B. Selector("dynamicMethod:")obwohl Sie die Gültigkeitsprüfung des Compilers verlieren. Wenn Sie dies tun, müssen Sie die ObjC-Namensregeln befolgen, einschließlich colons ( :) für jeden Parameter.

Selektorverfügbarkeit: Die vom Selektor referenzierte Methode muss der ObjC-Laufzeit ausgesetzt sein. In Swift 4 muss jeder Methode, die ObjC ausgesetzt ist, der Deklaration das @objcAttribut vorangestellt werden. (In früheren Versionen haben Sie dieses Attribut in einigen Fällen kostenlos erhalten, aber jetzt müssen Sie es explizit deklarieren.)

Denken Sie daran, dass privateSymbole auch nicht der Laufzeit ausgesetzt sind - Ihre Methode muss mindestens internalsichtbar sein.

Schlüsselpfade: Diese beziehen sich auf Selektoren, sind aber nicht ganz mit diesen identisch. Auch für diese gibt es in Swift 3 eine spezielle Syntax: z chris.valueForKeyPath(#keyPath(Person.friends.firstName)). Siehe SE-0062 für Details. Und noch mehr KeyPathDinge in Swift 4 , stellen Sie also sicher, dass Sie die richtige KeyPath-basierte API anstelle von Selektoren verwenden, falls zutreffend.

Weitere Informationen zu Selektoren finden Sie unter Interaktion mit Objective-C-APIs unter Verwenden von Swift mit Cocoa und Objective-C .

Hinweis: Vor Swift 2.2 Selectorkonform StringLiteralConvertible, sodass Sie möglicherweise alten Code finden, in dem bloße Zeichenfolgen an APIs übergeben werden, die Selektoren verwenden. Sie sollten "In aktuelle Swift-Syntax konvertieren" in Xcode ausführen, um diese zu verwenden #selector.

Rickster
quelle
8
Wenn Sie eine Zeichenfolge mit dem funktionierenden Funktionsnamen einfügen, funktioniert NSSelectorFromString () ebenfalls.
Arbitur
7
Ich möchte erwähnen, dass "Interaktion mit Objective-C-APIs" zwar auf der Website enthalten ist, jedoch NICHT im Buch "The Swift Programming Language".
10
Dies sollte wahrscheinlich erwähnen, dass der Selektor am Ende ein ":" benötigt, wenn er ein Argument benötigt. (ZB test () -> "test" & test (this: String) -> "test:")
Daniel Schlaug
2
Es sollte auch darauf hingewiesen werden, dass die Cocoa-Frameworks einen Methodennamen im Objective-C-Stil erwarten. Wenn Ihre Methode ein Argument akzeptiert, benötigen Sie ein ':'. Wenn 2 Argumente verwendet werden, size:andShape:benötigen Sie bei einem Namen des ersten Arguments möglicherweise ein With, dh initWithData:fürfunc init(Data data: NSData)
JMFR
6
Gibt es eine Möglichkeit, eine Validierung hinzuzufügen, um den "Selektor" als Zeichenfolge zu übergeben? IE Compiler warnen uns, wenn wir falsch
schreiben
86

Hier ist ein kurzes Beispiel für die Verwendung der SelectorKlasse in Swift:

override func viewDidLoad() {
    super.viewDidLoad()

    var rightButton = UIBarButtonItem(title: "Title", style: UIBarButtonItemStyle.Plain, target: self, action: Selector("method"))
    self.navigationItem.rightBarButtonItem = rightButton
}

func method() {
    // Something cool here   
}

Beachten Sie, dass die als Zeichenfolge übergebene Methode zur Laufzeit fehlschlägt, nicht zur Kompilierungszeit und Ihre App zum Absturz bringt. Achtung

Oscar Swanros
quelle
13
was schrecklich ist ... gibt es eine Art "NSStringFromSelector"?
Lena Bru
11
Ich kann nicht glauben, dass sie für ungeprüfte Selektoren entwickelt wurden, da objc dies hatte
malhal
4
@malcomhall: @selectorist praktisch, aber es wird nicht so formal durchgesetzt, wie Sie vielleicht denken. "Nicht deklarierter Selektor" ist lediglich eine Warnung des Compilers, da zur Laufzeit immer neue Selektoren eingeführt werden können. Überprüfbare / überarbeitbare Selektorreferenzen in Swift wären jedoch eine gute Anforderung für Funktionen .
Rickster
2
Diese Antwort ist hilfreich, aber die Antwort unten mit @objc ist angemessener.
Cynistersix
Wenn Sie die Selektorzeichenfolge als Variable oder Parameter übergeben, müssen Sie dem Compiler mithilfe der Selector () - Funktion mitteilen, dass es sich um einen Selektor handelt. danke
levous
46

Wenn Ihre (Swift-) Klasse nicht von einer Objective-C-Klasse abstammt, müssen Sie am Ende der Zeichenfolge für den Zielmethodennamen einen Doppelpunkt haben und die Eigenschaft @objc mit Ihrer Zielmethode verwenden, z

var rightButton = UIBarButtonItem(title: "Title", style: UIBarButtonItemStyle.Plain, target: self, action: Selector("method"))

@objc func method() {
    // Something cool here   
} 

Andernfalls wird zur Laufzeit der Fehler "Nicht erkannter Selektor" angezeigt.

user3771857
quelle
3
1. Selektoren mit einem Doppelpunkt müssen ein Argument annehmen. 2. Laut Apple-Dokumenten sollten die Aktionen des Timers das NSTimer-Argument annehmen. 3. Das SelectorSchlüsselwort ist nicht obligatorisch. In diesem Fall muss die Unterschrift also@objc func method(timer: NSTimer) {/*code*/}
Yevhen Dubinin
@objcarbeitete für mich. Ich musste nicht timer: NSTimerin meine Methodensignatur aufnehmen, damit sie aufgerufen werden konnte.
Mike Taverne
32

Swift 2.2+ und Swift 3 Update

Verwenden Sie den neuen #selectorAusdruck, wodurch die Verwendung von Zeichenfolgenliteralen entfällt, wodurch die Verwendung weniger fehleranfällig wird. Als Referenz:

Selector("keyboardDidHide:")

wird

#selector(keyboardDidHide(_:))

Siehe auch: Swift Evolution Proposal

Hinweis (Swift 4.0):

Bei Verwendung #selectormüssten Sie die Funktion als markieren@objc

Beispiel:

@objc func something(_ sender: UIButton)

Kyle Clegg
quelle
26

Swift 4.0

Sie erstellen den Selektor wie unten.

1. Fügen Sie das Ereignis einer Schaltfläche wie folgt hinzu:

button.addTarget(self, action: #selector(clickedButton(sender:)), for: UIControlEvents.touchUpInside)

und die Funktion wird wie folgt sein:

@objc func clickedButton(sender: AnyObject) {

}
Pravin Salame
quelle
4
Sie haben vergessen, @objcvorher zu setzen, funcwas in Swift 4 erforderlich ist.
Vahid Amiri
24

Für zukünftige Leser stellte ich fest, dass ich ein Problem hatte und einen unrecognised selector sent to instanceFehler erhielt, der durch das Markieren des Ziels funcals privat verursacht wurde.

Das func MUSS öffentlich sichtbar sein, um von einem Objekt mit einem Verweis auf einen Selektor aufgerufen zu werden.

Rob Sanders
quelle
13
es nicht hat , um öffentlich Sie immer noch die Methode privat halten können , aber hinzufügen , objcbevor es Erklärung. Bsp.: @objc private func foo() { ...Dann können Sie "foo"als Selektor verwenden, wie Sie
möchten
Es kann auch sein internal, dass kein Zugriffsmodifikator angegeben wird. Ich benutze oft dieses Muster://MARK: - Selector Methods\n extension MyController {\n func buttonPressed(_ button: UIButton) {
Sajjon
19

Nur für den Fall, dass jemand anderes das gleiche Problem mit NSTimer hat, bei dem keine der anderen Antworten das Problem behoben hat, ist es wirklich wichtig zu erwähnen, dass Sie eine Klasse verwenden, die weder direkt noch tief in der Hierarchie von NSObject erbt ( zB manuell erstellte schnelle Dateien), keine der anderen Antworten funktioniert, selbst wenn Folgendes angegeben ist:

let timer = NSTimer(timeInterval: 1, target: self, selector: "test", 
                    userInfo: nil, repeats: false)
func test () {}

Ohne etwas anderes zu ändern, als nur die Klasse von NSObject erben zu lassen, wurde der Fehler "Nicht erkannter Selektor" nicht mehr angezeigt und meine Logik funktionierte wie erwartet.

Martin Cazares
quelle
Das Problem bei dieser Alternative ist, dass Sie eine Klasse (sagen wir ViewController) nicht so ändern können, dass sie von NSObject erbt, da Sie die von der ViewController-Klasse implementierten Inhalte benötigen (z. B. viewDidLoad ()). Irgendeine Idee, wie man eine Swift-Funktion in einem ViewController mit NSTimer aufruft? ... e
eharo2
1
UIViewController erbt bereits von NSObject, die meisten Klassen, die vom SDK verfügbar gemacht werden. Dieses Beispiel gilt für selbst erstellte Klassen, die NSTimer-Funktionalität erfordern ...
Martin Cazares
14

Wenn Sie einen Parameter vom NSTimer an die Funktion übergeben möchten, ist hier Ihre Lösung:

var somethingToPass = "It worked"

let timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: "tester:", userInfo: somethingToPass, repeats: false)

func tester(timer: NSTimer)
{
    let theStringToPrint = timer.userInfo as String
    println(theStringToPrint)
}

Fügen Sie den Doppelpunkt in den Auswahltext ein (Tester :), und Ihre Parameter gehen in userInfo.

Ihre Funktion sollte NSTimer als Parameter verwenden. Extrahieren Sie dann einfach userInfo, um den übergebenen Parameter abzurufen.

Roller
quelle
3
Ich habe NSTimer (0.01, target: self, ...) verwendet, was NICHT funktioniert hat, wohingegen NSTimer.scheduledTimerWithTimeInterval (0.01, ..) funktioniert hat? Seltsam, aber danke @Scooter für deine Antwort!
iOS-Coder
1
@ iOS-Coder, der nur einen Timer mit dem Initialisierer erstellt, scheduledTimerWith...fügt ihn nicht zu einem Runloop hinzu, während er automatisch zum aktuellen Runloop hinzugefügt wird - daher gibt es hier überhaupt kein seltsames Verhalten;)
David Ganster
1
@ David danke für deinen Vorschlag. Ich denke, mein Missverständnis sollte entweder in die Kategorie STFW oder RTFA (Read The Fing API) gehören.
iOS-Coder
1
Mach dir keine Sorgen, niemand kann erwarten, die Dokumentation über jede einzelne Methode in jeder API zu lesen;)
David Ganster
10

Selektoren sind eine interne Darstellung eines Methodennamens in Objective-C. In Objective-C würde "@selector (methodName)" eine Quellcodemethode in einen Datentyp von SEL konvertieren. Da Sie die @ selector-Syntax in Swift nicht verwenden können (Rickster ist dort aktiv), müssen Sie den Methodennamen manuell direkt als String-Objekt angeben oder ein String-Objekt an den Selector-Typ übergeben. Hier ist ein Beispiel:

var rightBarButton = UIBarButtonItem(
    title: "Logout", 
    style: UIBarButtonItemStyle.Plain, 
    target: self, 
    action:"logout"
)

oder

var rightBarButton = UIBarButtonItem(
    title: "Logout", 
    style: UIBarButtonItemStyle.Plain, 
    target: self, 
    action:Selector("logout")
)
Jon Tsiros
quelle
8

Swift 4.1
Mit Beispiel einer Tap-Geste

let gestureRecognizer = UITapGestureRecognizer()
self.view.addGestureRecognizer(gestureRecognizer)
gestureRecognizer.addTarget(self, action: #selector(self.dismiss(completion:)))

// Use destination 'Class Name' directly, if you selector (function) is not in same class.
//gestureRecognizer.addTarget(self, action: #selector(DestinationClass.dismiss(completion:)))


@objc func dismiss(completion: (() -> Void)?) {
      self.dismiss(animated: true, completion: completion)
}

Weitere Informationen zu: Auswahlausdruck finden Sie im Apple-Dokument

Krunal
quelle
Bitte hör auf damit. Es hilft niemandem. Wie unterscheidet sich das von Swift 3.1? Und warum hielten Sie es für notwendig, eine weitere Antwort hinzuzufügen, wenn es bereits etwa 20 Antworten gibt?
Fogmeister
Der Anrufwähler ist in Swift 4 anders. Probieren Sie diese Antworten in Swift 4 aus und sehen Sie. Keine diese funktionieren ohne Bearbeitung. Bitte markieren Sie keine Erklärung als Spam, ohne deren Impotenz sicherzustellen
Krunal
Gibt es einen Grund, warum Sie die vorhandene, akzeptierte Antwort nicht bearbeiten konnten? Es würde es tatsächlich nützlich machen, anstatt am Ende einer langen Liste von Antworten hinzuzufügen. Die Schaltfläche "Bearbeiten" ist aus einem bestimmten Grund vorhanden.
Fogmeister
Welcher Teil davon unterscheidet sich von Swift 3?
Fogmeister
2
Sie müssen das objc-Tag zu allen Selektoren für Swift 4 hinzufügen. Dies ist die richtige Antwort. Und du sollst die Antworten anderer Leute nicht bearbeiten, um ihre Bedeutung zu ändern. @ Krunal ist völlig richtig.
Unome
6
// for swift 2.2
// version 1
buttton.addTarget(self, action: #selector(ViewController.tappedButton), forControlEvents: .TouchUpInside)
buttton.addTarget(self, action: #selector(ViewController.tappedButton2(_:)), forControlEvents: .TouchUpInside)

// version 2
buttton.addTarget(self, action: #selector(self.tappedButton), forControlEvents: .TouchUpInside)
buttton.addTarget(self, action: #selector(self.tappedButton2(_:)), forControlEvents: .TouchUpInside)

// version 3
buttton.addTarget(self, action: #selector(tappedButton), forControlEvents: .TouchUpInside)
buttton.addTarget(self, action: #selector(tappedButton2(_:)), forControlEvents: .TouchUpInside)

func tappedButton() {
  print("tapped")
}

func tappedButton2(sender: UIButton) {
  print("tapped 2")
}

// swift 3.x
button.addTarget(self, action: #selector(tappedButton(_:)), for: .touchUpInside)

func tappedButton(_ sender: UIButton) {
  // tapped
}

button.addTarget(self, action: #selector(tappedButton(_:_:)), for: .touchUpInside)

func tappedButton(_ sender: UIButton, _ event: UIEvent) {
  // tapped
}
John Lee
quelle
Es wäre schöner und lehrreicher gewesen, wenn Sie ein Beispiel hätten, das zwei oder drei Argumente für Swift3 oder Swift4 enthält. Vielen Dank.
Nyxee
5
Create Refresh control using Selector method.   
    var refreshCntrl : UIRefreshControl!
    refreshCntrl = UIRefreshControl()
    refreshCntrl.tintColor = UIColor.whiteColor()
    refreshCntrl.attributedTitle = NSAttributedString(string: "Please Wait...")
    refreshCntrl.addTarget(self, action:"refreshControlValueChanged", forControlEvents: UIControlEvents.ValueChanged)
    atableView.addSubview(refreshCntrl)

// Kontrollmethode aktualisieren

func refreshControlValueChanged(){
    atableView.reloadData()
    refreshCntrl.endRefreshing()

}
Renish Dadhaniya
quelle
5

Da Swift 3.0 veröffentlicht wird, ist es noch etwas subtiler, eine targetAction für angemessen zu erklären

class MyCustomView : UIView {

    func addTapGestureRecognizer() {

        // the "_" is important
        let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(MyCustomView.handleTapGesture(_:)))
        tapGestureRecognizer.numberOfTapsRequired = 1
        addGestureRecognizer(tapGestureRecognizer)
    }

    // since Swift 3.0 this "_" in the method implementation is very important to 
    // let the selector understand the targetAction
    func handleTapGesture(_ tapGesture : UITapGestureRecognizer) {

        if tapGesture.state == .ended {
            print("TapGesture detected")
        }
    }
}
LukeSideWalker
quelle
4

Beim Benutzen performSelector()

/addtarget()/NStimer.scheduledTimerWithInterval() Methoden Ihre Methode (passend zum Selektor) sollte als markiert sein

@objc
For Swift 2.0:
    {  
        //...
        self.performSelector(“performMethod”, withObject: nil , afterDelay: 0.5)
        //...


    //...
    btnHome.addTarget(self, action: “buttonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
    //...

    //...
     NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector : “timerMethod”, userInfo: nil, repeats: false)
    //...

}

@objc private func performMethod() {}
@objc private func buttonPressed(sender:UIButton){.
}
@objc private func timerMethod () {.
}

Für Swift 2.2 müssen Sie '#selector ()' anstelle von Zeichenfolge und Selektorname schreiben, damit die Möglichkeit von Rechtschreibfehlern und Abstürzen aufgrund dessen nicht mehr besteht. Unten ist ein Beispiel

self.performSelector(#selector(MyClass.performMethod), withObject: nil , afterDelay: 0.5)
Sschunara
quelle
3

Sie erstellen den Selektor wie unten.
1.

UIBarButtonItem(
    title: "Some Title",
    style: UIBarButtonItemStyle.Done,
    target: self,
    action: "flatButtonPressed"
)

2.

flatButton.addTarget(self, action: "flatButtonPressed:", forControlEvents: UIControlEvents.TouchUpInside)

Beachten Sie, dass die @ selector-Syntax nicht mehr vorhanden ist und durch einen einfachen String ersetzt wird, der die aufzurufende Methode benennt. Es gibt einen Bereich, in dem wir uns alle einig sein können, dass die Ausführlichkeit im Weg steht. Wenn wir deklarieren, dass es eine Zielmethode namens flatButtonPressed gibt, schreiben wir natürlich eine:

func flatButtonPressed(sender: AnyObject) {
  NSLog("flatButtonPressed")
}

Stellen Sie den Timer ein:

    var timer = NSTimer.scheduledTimerWithTimeInterval(1.0, 
                    target: self, 
                    selector: Selector("flatButtonPressed"), 
                    userInfo: userInfo, 
                    repeats: true)
    let mainLoop = NSRunLoop.mainRunLoop()  //1
    mainLoop.addTimer(timer, forMode: NSDefaultRunLoopMode) //2 this two line is optinal

Um vollständig zu sein, hier ist die flatButtonPressed

func flatButtonPressed(timer: NSTimer) {
}
Daxesh Nagar
quelle
Haben Sie eine Quelle für " Beachten Sie, dass die @ selector-Syntax weg ist "?
Winklerrr
3

Ich fand viele dieser Antworten hilfreich, aber es war nicht klar, wie man das mit etwas macht, das kein Knopf ist. Ich habe einem UILabel schnell einen Gestenerkenner hinzugefügt und mich schwer getan. Nachdem ich alles oben gelesen habe, hat Folgendes für mich funktioniert:

let tapRecognizer = UITapGestureRecognizer(
            target: self,
            action: "labelTapped:")

Wo der "Selektor" deklariert wurde als:

func labelTapped(sender: UILabel) { }

Beachten Sie, dass es öffentlich ist und dass ich nicht die Selector () -Syntax verwende, aber es ist auch möglich, dies zu tun.

let tapRecognizer = UITapGestureRecognizer(
            target: self,
            action: Selector("labelTapped:"))
cynistersix
quelle
3

Wenn Sie #selector verwenden, wird Ihr Code beim Kompilieren überprüft, um sicherzustellen, dass die Methode, die Sie aufrufen möchten, tatsächlich vorhanden ist. Noch besser ist, wenn die Methode nicht vorhanden ist, wird ein Kompilierungsfehler angezeigt: Xcode weigert sich, Ihre App zu erstellen, und verbannt so, dass eine weitere mögliche Fehlerquelle vergessen wird.

override func viewDidLoad() {
        super.viewDidLoad()

        navigationItem.rightBarButtonItem =
            UIBarButtonItem(barButtonSystemItem: .Add, target: self,
                            action: #selector(addNewFireflyRefernce))
    }

    func addNewFireflyReference() {
        gratuitousReferences.append("Curse your sudden but inevitable betrayal!")
    }
Schneller Entwickler
quelle
2

Es kann hilfreich sein zu notieren, wo Sie das Steuerelement einrichten, das die Aktion auslöst.

Ich habe beispielsweise festgestellt, dass ich beim Einrichten eines UIBarButtonItem die Schaltfläche in viewDidLoad erstellen musste, da sonst eine nicht erkannte Selektorausnahme angezeigt wird.

override func viewDidLoad() {
    super.viewDidLoad() 

    // add button
    let addButton = UIBarButtonItem(image: UIImage(named: "746-plus-circle.png"), style: UIBarButtonItemStyle.Plain, target: self, action: Selector("addAction:"))
    self.navigationItem.rightBarButtonItem = addButton
}

func addAction(send: AnyObject?) {     
    NSLog("addAction")
}
Michael Peterson
quelle
1

Ändern Sie als einfache Zeichenfolgenbenennung in der Methode, die die Selektorsyntax aufruft

var timer1 : NSTimer? = nil
timer1= NSTimer(timeInterval: 0.1, target: self, selector: Selector("test"), userInfo: nil, repeats: true)

Geben Sie danach func test () ein.

Thar Htet
quelle
1

selectorist ein Wort aus der Objective-CWelt und Sie können es von verwenden, Swiftum die Möglichkeit zu haben, von dort Objective-Caus aufzurufen. Swift Es ermöglicht Ihnen, zur Laufzeit Code auszuführen

Vor Swift 2.2der Syntax steht:

Selector("foo:")

Da ein Funktionsname Selectorals String-Parameter ("foo") übergeben wird, ist es nicht möglich, einen Namen in der Kompilierungszeit zu überprüfen . Als Ergebnis können Sie einen Laufzeitfehler erhalten:

unrecognized selector sent to instance

Nach Swift 2.2+der Syntax lautet:

#selector(foo(_:))

Die automatische Vervollständigung von Xcode hilft Ihnen, eine richtige Methode aufzurufen

yoAlex5
quelle
0

Für Swift 3

// Beispielcode zum Erstellen eines Timers

Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(updateTimer)), userInfo: nil, repeats: true)

WHERE
timeInterval:- Interval in which timer should fire like 1s, 10s, 100s etc. [Its value is in secs]
target:- function which pointed to class. So here I am pointing to current class.
selector:- function that will execute when timer fires.

func updateTimer(){
    //Implemetation 
} 

repeats:- true/false specifies that timer should call again n again.
CrazyPro007
quelle
0

Auswahl in Swift 4:

button.addTarget(self, action: #selector(buttonTapped(sender:)), for: UIControlEvents.touchUpInside)
Mahesh Chaudhari
quelle
-1

Für schnelle 3

let timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(self.test), userInfo: nil, repeats: true)

Funktionsdeklaration In derselben Klasse:

@objc func test()
{
    // my function
} 
Mustajab Haider
quelle
Wenn das Ziel selbst ist, muss es nicht selfim Selektor vorhanden sein. Dies sollte ausreichen:let timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(test), userInfo: nil, repeats: true)
Mithra Singam