Nathan Modern Nathan Modern - 2 months ago 15
Swift Question

Updating variable of View Controller using App Delegate

So I am basically trying to display the push notification received in the application.
I am trying to update the text of a view controller when a notification is received. However, every time I try to update the view controller, I get an error:

fatal error: unexpectedly found nil while unwrapping an Optional value


Here is my appdelegate snippet:

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject],
fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired till the user taps on the notification launching the application.
// TODO: Handle data of notification

// Print message ID.

print("Message ID: \(userInfo["gcm.message_id"]!)")



let vc = FirstViewController()


vc.notificationText = "Test"
print (vc.notificationText)
vc.updateText()

// Print full message.
print("%@", userInfo)
}


Here is my View Controller:

class FirstViewController: UIViewController {


@IBOutlet weak var notificationLabel: UILabel!
var notificationText = "No notifications"

@IBAction func logOut(sender: AnyObject) {
try! FIRAuth.auth()!.signOut()
LogOutComplete()
}

func LogOutComplete() {
let mainStoryboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
let logIn : UIViewController = mainStoryboard.instantiateViewControllerWithIdentifier("LogIn") as UIViewController
self.presentViewController(logIn, animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()

notificationLabel.text = notificationText

//notificationLabel.text = notificationText
// Do any additional setup after loading the view.
}

/*override func viewWillAppear(animated: Bool) {
notificationLabel.text = notificationText
}*/

func updateText () {
notificationLabel.text = notificationText
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}


I really don't know why it is giving me this error. Maybe someone could explain and help me with the solution. All help is appreciated!

Answer

Edited for Swift 2.2:

You are creating a new instance of FirstViewController in the application: didReceiveRemoteNotification method. So you are updating the property of a different instance of FirstViewController than you are meaning to. The one you are updating is not being displayed. The error is coming because updateText() is being called but the storyboard isn't initialized so notificationLabel is still nil.

To do what you are trying to, instead pass the notification to the view controller using a notification post and have FirstViewController added as an observer:

In your AppDelegate, change the body to the following:

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject],
             fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired till the user taps on the notification launching the application.
// TODO: Handle data of notification

// Print message ID.

print("Message ID: \(userInfo["gcm.message_id"]!)")
NotificationCenter.default.post(name: "Add_Notification_Post_Name_Here", object: nil,
                                                              userInfo: userInfo)

}

In FirstViewController, add an observer to listen for notification posts:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    NotificationCenter.default.addObserver(self, selector: Some_Method_Name:, name: "Add_Notification_Post_Name_Here", object: nil)
}

In FirstViewController, add a method to handle this notification post:

func Some_Method_Name(_ notification: NSNotification) {

guard let userInfo = notification.userInfo else {
        return
    }
    guard let payload = userInfo["Some_Message_Key_Here"] as? NSString  else {
        return
    }
    notificationText = String(payload)
    updateText()
}

This method converts your package to a payload of type String to assign to your notification text. Then you call your updateText() function.