Search code examples
iosswiftnsnotificationcenter

Nil when passing information with NSNotifications?


I've got a class that controls dragging UIButtons on the screen. I'm wanting to capture the tag/final position of the button on touchesEnded.

I've got in my DragImageClass:

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {

    let dict =  ["position":String(self.center),"tag": String(self.tag)]

    NSNotificationCenter.defaultCenter().postNotificationName("buttonDropped", object: nil, userInfo: dict)

    print(dict["position"]) // Does get printed
    print("Should have sent") // Does get called
}

then in my main view where I'm needing the info I've got :

My observer:

NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(testController.touchesStopped(_:)), name: "buttonDropped", object: nil)

My function:

func touchesStopped(notif : AnyObject) {
    if let dict = notif.object as? NSDictionary { //Some error with this data type I guess?
        let position = dict["position"]
        let tag = dict["tag"]
        print(position)  // doesn't get printed
        print(tag) // doesn't get printed
    }
}

Any ideas why I'm getting nil back from those values? When I try to force unwrap it's just giving me the "Thread bad instruction" thing.


Solution

  • As you can see in your call, the object is nil because you pass the dictionary as the userInfo (which is the right way to do it) :

    NSNotificationCenter.defaultCenter().postNotificationName("buttonDropped", object: nil, userInfo: dict)
    

    So in order to get that dictionary back, don't use the object property of the notification, use the userInfo property :

    func touchesStopped(notif: NSNotification) {
        if let dict = notif.userInfo {
            let position = dict["position"]
            let tag = dict["tag"]
            print(position)
            print(tag)
        }
    }
    

    Side note: Converting a point to a string and back to a point is going to be a pain, you should probably use NSValue instead like this :

    let dict: [String:AnyObject] = [
        "position": NSValue(CGPoint: self.center),
        "tag": self.tag
    ]
    let position = (dict["position"] as? NSValue)?.CGPointValue()
    let tag = dict["tag"] as? Int