Variable von AppDelegate in allen Klassen verfügbar machen?

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Variable von AppDelegate in allen Klassen verfügbar machen?

    Hallo Freunde der Programmierung,

    ich stehe vor einem Rätsel.

    Ich wage mich gerade an APNs also die Push Notifications und komme an einem Punkt einfach nicht weiter.

    In meiner Test-App bekomme ich in der AppDelegate Klasse den deviceToken meines Testgerätes in einer Methode per println ausgegeben.

    Über den deviceToken und ein PHP Script auf meinem Server kann ich erfolgreich Push Notifications an das Testiphone senden.

    Jetzt muss ich aber den deviceToken irgendwie in den ViewController bekommen und das klappt einfach nicht.

    Ich bin mittlerweile so weit, das ich im ViewController mit folgendem Code eine Variable aus der AppDelegate auslesen kann.

    Quellcode

    1. override func viewDidLoad() {
    2. super.viewDidLoad()
    3. let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
    4. let deviceToken = appDelegate.testVAr
    5. println(deviceToken)
    6. }
    Alles anzeigen


    das Problem ist aber, das diese Variable direkt am Anfang der AppDelegate Klasse definiert werden muss, damit ich den Wert geliefert bekomme.

    Mein deviceToken selber wird aber in folgender Methode in der AppDelegate Klasse ausgelesen:

    Quellcode

    1. func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
    2. println(deviceToken)
    3. }


    Jetzt dachte ich ok dann erstelle ich die Variable oben in der AppDelegate Klasse (vor allen Methoden) und überschreibe den Inhalt in meiner Methode.

    Quellcode

    1. class AppDelegate: UIResponder, UIApplicationDelegate {
    2. var testVar: String?
    3. func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
    4. println(deviceToken)
    5. testVar = deviceToken
    6. }


    Tja leider nicht. Es wird kein Wert übergeben.

    Habt ihr eine Idee wo mein Fehler liegt?

    Vielen Dank :)
  • Anstatt das Token zu holen, kannst du es auch übergeben. Dazu kannst du dir im App-Delegate über self.window.rootViewController den untersten Viewcontroller holen, und dich zu dem entsprechenden Viewcontroller durchhangeln. Klingt schlimm, ist es auch. ;)

    Eleganter ist es, das Token per Benachrichtigung in der App zu versenden, wobei sich der Viewcontroller natürlich als Empfänger registrieren muss.
    „Meine Komplikation hatte eine Komplikation.“
  • macmoonshine schrieb:

    Anstatt das Token zu holen, kannst du es auch übergeben. Dazu kannst du dir im App-Delegate über self.window.rootViewController den untersten Viewcontroller holen, und dich zu dem entsprechenden Viewcontroller durchhangeln. Klingt schlimm, ist es auch. ;)


    das teste ich direkt mal aus. Letztendlich brauche ich den deviceToken nur im 1. ViewController. Dann sollte es ja genau das richtige sein :D

    macmoonshine schrieb:

    Eleganter ist es, das Token per Benachrichtigung in der App zu versenden, wobei sich der Viewcontroller natürlich als Empfänger registrieren muss.


    Sollte der oben genannte Weg von dir nicht zum Ziel führen, dann werde ich es über die Benachrichtigungen versuchen. Das Thema schaue ich mir auf jeden Fall mal an.

    Danke dir für die schnelle Hilfe :)
  • Man kann auch rekursiv über alle ViewController iterieren, und wenn die entsprechende Property vorhanden ist (z.B. mit einem Protokoll sicher zu stellen), weist man den Wert zu - sind auch nur 10 Zeilen, und ist ein ganz brauchbares Muster, wenn man einen Wert an mehrere unbekannte Empfänger übermitteln will.
  • Lieber das Ganze direkt mit Benachrichtigungen oder von mir aus auch KVO direkt ordentlich machen.

    t-no schrieb:

    da wird die Versuchung durch Globals doch schon ziemlich groß...

    Nö, keinesfalls. Das würde auch hier nicht helfen, da die App das Device-Token in der Regel erst dann erhält, wenn sie die Viewcontroller bereits anzeigt. Das ist ja schließlich auch genau das Problem des OP.
    „Meine Komplikation hatte eine Komplikation.“


  • Bitte?

    macmoonshine schrieb:

    DKCode schrieb:

    Sollte der oben genannte Weg von dir nicht zum Ziel führen, dann werde ich es über die Benachrichtigungen versuchen.

    Mach es lieber umgekehrt. ;)


    Ja ich komme mit dem anderen Weg auch nicht weiter.
    Habe das nun so versucht:

    Quellcode

    1. ​let storyboard = UIStoryboard(name: "Main", bundle: nil)
    2. let firstView = storyboard.instantiateViewControllerWithIdentifier("ViewController") as ViewController
    3. firstView.variable = "xxxx"
    4. self.window?.rootViewController = firstView;


    dann bekomme ich aber nur ein "Thread 1: signal SIGABRT"

    mache ich aus "as ViewController" > "as UIViewController" dann erhalte ich den Error das "variable" kein Member von UIViewController ist.

    Ich schau mir dann mal die Benachrichtigungen an. Hatte eben auch die Idee den deviceToken als CoreData abzuspeichern. Aber das ist dann PlanB, wenn ich bei den Benachrichtigungen nicht weiter kommen :)

    t-no schrieb:

    Man kann auch rekursiv über alle ViewController iterieren, und wenn die entsprechende Property vorhanden ist (z.B. mit einem Protokoll sicher zu stellen), weist man den Wert zu - sind auch nur 10 Zeilen, und ist ein ganz brauchbares Muster, wenn man einen Wert an mehrere unbekannte Empfänger übermitteln will.


    das klingt höchst professionell ^^ aber leider ist mir das noch etwas zu hoch. Bin ja noch fleißig am lernen.

    t-no schrieb:

    Hässlich wird es, wenn man es mit ViewControllern zu tun hat, die erst irgendwann mitten in der Lebenszeit der App erzeugt werden - da wird die Versuchung durch Globals doch schon ziemlich groß...


    Bei mir ist es ja direkt der 1. ViewController der beim Start der App angezeigt wird. Daher sollte ich da doch eigentlich keine Probleme haben. Wobei so eine Globale Variable für spätere Zwecke vielleicht doch ganz gut wäre.
  • Mein Gott ich halt es echt nicht aus.

    Sich NSNotifications durchzulesen und zu verstehen dauert keine 30minuten. Dann zwei Zeilen in den Code, eine zum abschicken der Notifikation und eine zum registrieren und fertig!

    wie kommt man nur überhaupt diese vollkommen sinnfeien und abgefahrenen Ideen durch irgendwelche Vieww zu iterieren um einen Datenfluss zu realisieren? Das ist das absolute anti-MVC-Pattern. Schlimmer geht es wirklich nicht mehr.

    Claus
    2 Stunden Try & Error erspart 10 Minuten Handbuchlesen.

    Pre-Kaffee-Posts sind mit Vorsicht zu geniessen :)
  • macmoonshine schrieb:

    Lieber das Ganze direkt mit Benachrichtigungen oder von mir aus auch KVO direkt ordentlich machen.

    t-no schrieb:

    da wird die Versuchung durch Globals doch schon ziemlich groß...

    Nö, keinesfalls. Das würde auch hier nicht helfen, da die App das Device-Token in der Regel erst dann erhält, wenn sie die Viewcontroller bereits anzeigt. Das ist ja schließlich auch genau das Problem des OP.


    Genau. Ich hatte den Ablauf wohl noch nicht ganz durchschaut. Ich ging davon aus, das die ViewController erst nach der AppDelegate geladen werden. Aber so ist es natürlich klar, das ich keine Werte übergeben bekomme.
  • Thallius schrieb:

    Mein Gott ich halt es echt nicht aus.

    Sich NSNotifications durchzulesen und zu verstehen dauert keine 30minuten. Dann zwei Zeilen in den Code, eine zum abschicken der Notifikation und eine zum registrieren und fertig!

    wie kommt man nur überhaupt diese vollkommen sinnfeien und abgefahrenen Ideen durch irgendwelche Vieww zu iterieren um einen Datenfluss zu realisieren? Das ist das absolute anti-MVC-Pattern. Schlimmer geht es wirklich nicht mehr.

    Claus


    Sorry Claus, das ich dich hier aufrege, aber ich kann aus Erfahrung leider noch nicht einschätzen, welcher Weg der bessere ist. Daher teste ich mich einfach durch alles was man mir aufzeigt :)
  • macmoonshine schrieb:

    Nö, keinesfalls. Das würde auch hier nicht helfen, da die App das Device-Token in der Regel erst dann erhält, wenn sie die Viewcontroller bereits anzeigt. Das ist ja schließlich auch genau das Problem des OP.

    Ich habe ausdrücklich gesagt, dass sich der Absatz gerade nicht auf diesen Fall bezieht.

    Thallius schrieb:

    wie kommt man nur überhaupt diese vollkommen sinnfeien und abgefahrenen Ideen durch irgendwelche Vieww zu iterieren um einen Datenfluss zu realisieren? Das ist das absolute anti-MVC-Pattern. Schlimmer geht es wirklich nicht mehr.

    Das Vorgehen nennt sich "dependency injection" und hat als einzige Lösung den Charme, nicht auf Globals angewiesen zu sein - und ist auch nicht wirklich kompliziert:

    Quellcode

    1. extension UIViewController {
    2. func injectToken(token: Token) {
    3. if let current = self as? TokenUser {
    4. current.token = token
    5. }
    6. for current in self.childViewControllers {
    7. current.injectToken(token)
    8. }
    9. }
    10. }

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von t-no ()

  • Ok ich komme der Sache näher ^^

    ich habe nun in der appDelegate Klasse:

    Quellcode

    1. var userDeviceToken = deviceToken
    2. NSNotificationCenter.defaultCenter().postNotificationName("NotificationIdentifier", object: userDeviceToken)


    und in meiner ViewController Klasse:

    Quellcode

    1. var getUserDeviceToken: String!
    2. required init(coder aDecoder: NSCoder) {
    3. super.init(coder: aDecoder)
    4. NSNotificationCenter.defaultCenter().addObserver(self, selector: "methodOFReceivedNotication:", name:"NotificationIdentifier", object: nil)
    5. }
    6. func methodOFReceivedNotication(notification: NSNotification){
    7. let userDeviceToken = notification
    8. println(userDeviceToken)
    9. getUserDeviceToken = userDeviceToken
    10. }
    Alles anzeigen


    println(userDeviceToken) gibt mir den richtigen Wert aus. Aber ich kann "userDeviceToken" nicht in einen String umwandeln?
    Ich bekomme nur den Fehler "NSNotification is not a subtype of NSString"

    jetzt habe ich schon versucht das ganze mit "getUserDeviceToken = userDeviceToken as String!" und "getUserDeviceToken = String(userDeviceToken)" umzuwandeln,
    aber das haut nicht hin. Kann man die Notification nicht in einen String umwandeln? Ok ich weiß das der ein oder anderer bei dieser Frage bestimmt herzhaft lachen wird, aber was mache ich falsch? :D
  • DKCode schrieb:

    hm ich dachte das wäre der Weg den du Anfangs meintest.

    Halbrichtig: Der erste Vorschlag bestand darin, das Token weiterzugeben. Ich habe aber nicht geschrieben, dass du den Viewcontroller selber laden sollst. Auch diesen Code müsstest du in application:didRegisterForRemoteNotificationsWithDeviceToken: packen, und da hat die App wahrscheinlich schon den Rootview geladen. Wenn der Root-View das Token braucht, könnte das so aussehen:

    Quellcode

    1. (void)application:(UIApplication *)inApplication didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)inToken {
    2. MyViewController *theController = (MyViewController *)self.window.rootViewController;
    3. theController.deviceToken = inToken;
    4. }

    Sobald du jedoch eine etwas komplexere Navigationshierarchie hast, wird das aber ziemlich eklig. Deswegen habe ich dir den Weg über Benachrichtigungen empfohlen. ;)
    „Meine Komplikation hatte eine Komplikation.“

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von macmoonshine () aus folgendem Grund: NSString -> NSData (danke ghandi ;-)