2

I am building a Desktop Cocoa App. When the user clicks a button, if a resource is successfully downloaded, the application sends a local notification to the user. When the user click's the notification, I want to open the URL to the source of the downloaded resource. I am attempting to store the URL in the userInfo dictionary in UNMutableNotificationContent with an integer key.

I can see that the content is there before the notification request is added: [AnyHashable(0): "https://stackoverflow.com/questions/ask"], but it is empty in the delegate's handler: [:]

// helper method to create the notification
func notify(userInfo: [AnyHashable : Any] = [:]) {
  let uid = UUID().uuidString
  let content = UNMutableNotificationContent()
  content.title = self.title
  content.userInfo = userInfo
  content.sound = UNNotificationSound.default
  print("add notification userInfo \(content.userInfo)")
  let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)
  let request = UNNotificationRequest(identifier: uid, content: content, trigger: trigger)
  center.add(request) { (error) in
    print("add notification error \(error)")
  }
}

// notification click handler
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
  print("recieved notification userInfo: \(response.notification.request.content.userInfo)")
}

This is the only place notifications are being created, and I've verified that the request identifiers match.

notify() caller example

if let url = URL(string: "https://stackoverflow.com/questions/ask") {
  notificationDelegate.notify(userInfo: [0: url.absoluteString])                    
}
Community
  • 1
  • 1
sdc
  • 2,603
  • 1
  • 27
  • 40
  • The print out in the notify function shows the userInfo correctly: `[AnyHashable(0): "https://stackoverflow.com/questions/ask"]`, but the print out in the notification click handler shows an empty dictionary `[:]` – sdc Jan 14 '19 at 03:42
  • Is this the only place you're creating notifications? Do the request identifiers match? – jscs Jan 17 '19 at 01:41
  • @JoshCaswell yes to both of your questions. I’ve printed out the UUID during create and click and they match, but userInfo is still empty ¯\_(ツ)_/¯ – sdc Jan 17 '19 at 01:43
  • Bit of a stab, but try either `[NSNumber(value: 0) : url.absoluteString]` or just `["0" : url.absoluteString]` I.e., something other than a Swift `Int` for the key. – jscs Jan 17 '19 at 01:47
  • @JoshCaswell `["0": url.absoluteString]` did it. Can you post your comment as an answer so I can accept it – sdc Jan 17 '19 at 03:17

1 Answers1

0

The documentation for UNNotificationContent's userInfo property notes that the keys must be property list types. This means that they have to be one of a short list of types that are directly storable in a property list. Scalar-like types in this list include NSNumber, NSString, and NSDate.

The literal Swift Int 0 that you're using as a key should, as far as I know, be automatically bridged to NSNumber and therefore be legal as a key. It seems that is not happening.

You will have to use one of those plist types directly. If you want a number as a key, 0 as NSNumber ought to work (hopefully?), or NSNumber(value: 0). More commonly, I think, the key would be a string.

I think this is worth filing a radar about, especially since a Swift String apparently is bridged correctly and automatically (to an NSString). (An exception from the ObjC side to let us know that the dictionary can't be encoded, rather than silent disappearance, would also be nice...)

jscs
  • 63,694
  • 13
  • 151
  • 195