2016-07-25 4 views
-1

Ich verwende einen NSTimer, um eine Nachricht in einem Intervall zu senden. Hier ist der Code:Senden einer NSTimer-Zielnachricht an eine andere Klasse; Extrahieren seines userInfo-Parameters

{ 
    // .... 
    var params : [String] = [] 
    params.append(conversion) 
    params.append(message) 
    let timer = NSTimer(fireDate: date, interval: 60, target: self, selector: Selector("importTextMessage.sendMessage:"), userInfo: params, repeats: true) 

    NSRunLoop.mainRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes) 
    // ... 
} 


func sendMessage(params: [String]){ ...} 

Ich habe auch auf die Swift 2.2 Syntax versucht, zu ändern:

let timer = NSTimer(fireDate: date, interval: 60, target: self, selector: #selector(importTextMessage.sendMessage(_:)), userInfo: params, repeats: true) 

aber das ändert nichts.

Von jeder anderen Frage, die über den "Nicht erkannten Selektor an Instanz gesendet" gesendet wird, lautet die Antwort: "Schließen Sie einen Doppelpunkt in die Auswahl ein, damit er Argumente von UserInfo abrufen kann" Finde heraus, was falsch ist.

Was Hinweis:

Die Parameter für die Funktion und die in durch NSTimer userinfo übergebenen Parameter DO übereinstimmen. Sie sind beide Arrays von Strings.

Wenn es irgendetwas bedeutet, schlägt der Code fehl, während sendMessage aufgerufen wird. Es macht es nicht wirklich zu sendMessage.

Ich bin eine seltsame Warnung immer sagen, dass „Stringliteral ist kein gültiger Ziel-c-Selektor“

ich meinen Code versuchte Wechsel für meinen nachrichts den Timer als Argument zu nehmen, wie ein Benutzer vorgeschlagen: func sendMessage(timer: NSTimer){ aber das gibt immer noch den gleichen Fehler.

Vielen Dank für Ihre Hilfe im Voraus, ich weiß es zu schätzen.

EDIT: Hier ist die Funktion, die Zeit läuft: // alle Daten speichern @IBAction func saveText (Sender: ANYOBJECT) {var Telefon: Double var aktiv: Int var Frequenz: Double var message: String var Datum: NSDate

phone = Double(currentNumber)! 
    active = 1 
    message = myTextView.text 
    date = myDatePicker.date 

    switch self.frequency.selectedRowInComponent(0) { 
     case 0: 
      frequency = 1 
     case 1: 
      frequency = 3 
     case 2: 
      frequency = 6 
     case 3: 
      frequency = 24 
     case 4: 
      frequency = 168 
     case 5: 
      frequency = 744 
     default: 
      frequency = 8760 
    } 

    importTextMessage.seedMessage(phone, active: active, frequency: frequency, message: message, date: date) 

    print(date) 
    let conversion : String = "+1" + String(Int(phone)) 


    //importTextMessage.sendMessage("Ryan", to: conversion, message: message) 
    var params : [String] = [] 
    params.append(conversion) 
    params.append(message) 
    //importTextMessage.sendMessage(params) 

    let timer = NSTimer(fireDate: date, interval: 60, target: self, selector: #selector(importTextMessage.sendMessage(_:)), userInfo: params, repeats: true) 
    //   
    NSRunLoop.mainRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes) 

} 

EDIT: genaue Fehler mssg:

unerkannt Selektor Instanz gesendet 0x7ffe6b915460 2016-07- 25 13: 26: 09,092 Harras Ihrer Kate [53524: 9000621] *** App beenden aufgrund nicht abgefangene Ausnahme 'NSInvalidArgumentException', Grund: ‚- [Harass_Your_Kate.AddMessageViewController nachrichts:]: Unbekannter Selektor an Instanz gesendet 0x7ffe6b915460

Antwort

0

Die API von NSTimer ist so, dass der Empfänger (Zielfunktion) gut arbeitet man nehmen muss und nur einen Parameter vom Typ NSTimer.

https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSTimer_Class/#//apple_ref/occ/clm/NSTimer/scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:

Die Meldung, wenn die Timer-Feuer Ziel zu senden.

Der Selektor sollte die folgende Signatur haben: timerFireMethod: (einschließlich eines Doppelpunkts, um anzuzeigen, dass die Methode ein Argument akzeptiert). Der timer gibt selbst als das Argument, wodurch das Verfahren den folgenden Muster annehmen würde:

  • (void) timerFireMethod: (NSTimer *) timer

In Swift die Signatur must sein

edit: aktualisiert Ihren Code entsprechen genau

Hinweis: Swift 2.2 Syntax

class TextMessageViewController: UIViewController { 
    var importTextMessage: AddMessageViewController // init'd somehow 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     // ... 

     // Note how selector matches *the name of the class* 
     // As I understand it now, the sendMessage method 
     // is declared in the AddMessageViewController class, 
     // and importTextMessage is the name of the instance of that class. 
     // And we're in a different class now, TextMessageViewController, 
     // so using `self` does not make sense here. 
     let timer = NSTimer(fireDate: date, interval: 60, target: importTextMessage, 
      selector: #selector(AddMessageViewController.sendMessage(_:)), userInfo: params, repeats: true) 
     NSRunLoop.mainRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes) 
    } 
} 


class AddMessageViewController: UIViewController { 
    // func must not be private 
    func sendMessage(timer: NSTimer) { 
     // And now for example 
     print("params: \(timer.userInfo)") 
    } 
} 

Was Ihr userinfo Wörterbuch, das ist ein Eigenschaft des Timer-Objekt, kein Parameter an die Zielfunktion selbst.

Die SECOND Fehler ist, dass die Auswahl Syntax, um den Namen der Klasse verwenden ausfällt als erklärt, nicht der Name einer Instanz-Variable, die einen Verweis auf diese Klasse Instanz hat. Fügen Sie mehr Kontext in Ihre Frage ein, damit es schneller gelöst wird! Der THIRD Fehler ist, dass Sie den falschen Klassennamen verwenden. Wenn Sie self verwenden, muss der Klassenname im Selektor mit dem Namen der aktuellen Klasse übereinstimmen. Da Sie wirklich wollen, dass die Nachricht in eine andere Klasse geht, müssen Sie stattdessen , die Referenz verwenden. Siehe aktualisierten Code.

Ich denke, Sie noch nicht vollständig erfassen Objektreferenzen, und ihre Typen, und wie sie übereinstimmen müssen, und wie self ist nur die Referenz auf das kontextabhängige Objekt.

+0

Da dies richtig ist, sollte es wahrscheinlich nicht downvoted werden, aber ich bin neugierig, warum. – BaseZen

+0

Ich habe deine Antwort nicht abgelehnt, aber es hilft nicht beim Code. Ich habe genau das, was Sie und der andere Beantworter haben, aber es ändert den Fehler nicht. Es wird immer noch darauf hingewiesen, dass das Beenden der App aufgrund der nicht abgefangenen Ausnahme 'NSInvalidArgumentException', nicht erkannter Selektor an Instanz 0x13601f910 'gesendet wird. – Ryan

+0

Wenn Swift3 Unterstreichung vor dem ersten Parameter der Methode hinzufügt –

1

Aus doc:

der Timer geht selbst als Argument

so Ihre Timer anderes Argument Typen erwarten, NSTimer. Versuchen Sie diesen Code:

override func viewDidLoad() {   
    super.viewDidLoad() 

    var params : [String] = [] 
    params.append(conversion) 
    params.append(message) 
    let timer = NSTimer(fireDate: date, interval: 60, target: self, selector: #selector(sendMessage(_:)), userInfo: params, repeats: true) 
    NSRunLoop.mainRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes) 
} 

func sendMessage(sender: NSTimer) { 
    print(sender.userInfo as? [String]) 
} 

Dieser Code in meinem Standard-View-Controller

+0

Wenn ich diesen Code implementieren, ändert es nichts. Bevor sendMessage überhaupt ausgeführt wird, wird der Fehler ausgelöst. Wenn ich den Debugger durchlaufe, sind meine Parameter korrekt: p params ([String]) $ R0 = 2 Werte { [0] = "+1 ..... 52" [1] = "Hey, " } – Ryan

+0

Nach dem Verlassen der Funktion wird der Fehler angezeigt. Nachdem Sie an NSRunLoop vorbeigegangen sind, werden einige Assembly-Anweisungen ausgeführt und der Fehler ausgegeben. der Fehler ist NSInvalidArgumentException und nicht erkannt Selektor @Shadow – Ryan

+0

@Ryan Ich sehe keine Chance für Fehler für jetzt. Bitte gib etwas mehr Code an. Fehler kann in 'date' getter sein (ersetze es durch' NSDate() ') oder woanders sonst –