2
votes

I'm trying to pass data between tab bar controllers for the firts time, but it doesn't work. First Controller:

class FirstViewController: UIViewController {
@IBOutlet weak var sentNotificationLabel: UILabel!

override func viewDidLoad() {
    super.viewDidLoad()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "updateNotificationSentLabel:", name: mySpecialNotificationKey, object: nil)
}

@IBAction func notify() {
    NSNotificationCenter.defaultCenter().postNotificationName(mySpecialNotificationKey, object: nil, userInfo:["message":"Something"])
}

func updateNotificationSentLabel(notification:NSNotification) {
    let userInfo:Dictionary<String,String!> = notification.userInfo as Dictionary<String,String!>
    let messageString = userInfo["message"]
    sentNotificationLabel.text = messageString


}
}

Here it works ok, the sentNotificationLabel.text is "Something"

Second Controller is similiar, but he's not receiving any notification.

class SecondViewController: UIViewController {
@IBOutlet weak var notificationLabel: UILabel!

override func viewDidLoad() {
    super.viewDidLoad()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "updateLabel:", name: mySpecialNotificationKey, object: nil)
}

func updateLabel(notification:NSNotification) {
    let userInfo:Dictionary<String,String!> = notification.userInfo as Dictionary<String,String!>
    let messageString = userInfo["message"]
    notificationLabel.text = messageString


}

}

What I am doing wrong? How to change that?

2
Could you please describe your how you check that the notification is not being passed? Please remember that the view controller presented in the second tab will not be loaded until the user selects it. - siejkowski
Ok, You are right. When I first select the second tab bar and return to first controller - then it works. Can I load it before that? - migari

2 Answers

4
votes

The problem occurs because you are sending the message before the second view controller is registered.

NSNotificationCenter doesn't support sticky notifications - in other words, the message won't be cached. If no-one is listening at the very moment the notification is sent, it's just gone.

The easiest fix is to register your SecondViewController for notification in initialiser. However, than the UILabel is not yet loaded - we are before viewDidLoad callback. The solution is to cache the received message locally and use it to set the label text when it's ready.

class SecondViewController: UIViewController {

    @IBOutlet weak var notificationLabel: UILabel!
    var cachedMessage : String? = nil

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "updateLabel:", name: mySpecialNotificationKey, object: nil)
    }

    override func viewDidLoad() {
        if let cachedMessage = cachedMessage {
            notificationLabel.text = cachedMessage
        }
    }

    func updateLabel(notification:NSNotification) {
        let userInfo:Dictionary<String,String!> = notification.userInfo as Dictionary<String,String!>
        let messageString = userInfo["message"]
        if let notificationLabel = notificationLabel {
            notificationLabel.text = messageString
        } else {
            cachedMessage = messageString
        }
    }
}

Since controllers are being initialised before they are being displayed, the message should be delivered properly.

0
votes

Simply add observer in init method

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)

     NSNotificationCenter.defaultCenter().addObserver(self, selector: "addBadge", name: "addBadge", object: nil)

}