J.Doe
J.Doe

Reputation: 397

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.

Upvotes: 1

Views: 733

Answers (2)

Dan Loewenherz
Dan Loewenherz

Reputation: 11253

Looking at the documentation, NSNotification.userInfo is imported into Swift as [NSObject: AnyObject]?. Try this instead:

guard let notif = notif as? NSNotification,
   let dict = notif.userInfo as? [NSObject: AnyObject] else {
    return
}

let position = dict["position"]
let tag = dict["tag"]

print(position)  // doesn't get printed
print(tag) // doesn't get printed

Upvotes: 2

deadbeef
deadbeef

Reputation: 5563

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

Upvotes: 4

Related Questions