{"id":544,"date":"2014-08-31T10:41:49","date_gmt":"2014-08-31T16:41:49","guid":{"rendered":"http:\/\/dev.iachieved.it\/iachievedit\/?p=544"},"modified":"2016-09-18T08:11:26","modified_gmt":"2016-09-18T14:11:26","slug":"nsnotifications-with-userinfo-in-swift","status":"publish","type":"post","link":"https:\/\/dev.iachieved.it\/iachievedit\/nsnotifications-with-userinfo-in-swift\/","title":{"rendered":"NSNotifications with userInfo in Swift"},"content":{"rendered":"<p><b>Update 9\/18\/16:<\/b>  Swift 3.0 has brough even <i>more<\/i> changes to working with notifications and <code>userInfo<\/code>; come visit our <a href=\"http:\/\/dev.iachieved.it\/iachievedit\/notifications-and-userinfo-with-swift-3-0\/\">new article<\/a> on handling <code>Notification<\/code>s with Swift 3.0<\/p>\n<p><b>Update:<\/b>  Swift 2.2 has brought a number of changes; come visit our <a href=\"http:\/\/dev.iachieved.it\/iachievedit\/nsnotifications-with-userinfo-in-swift-2-2\/\">new article<\/a> on handling <code>NSNotification userInfo<\/code> in Swift.<\/p>\n<p>I frequently sit down intent on writing about one topic, only finding myself in a situation where I feel motivated to write about something else.  This is one such post.<\/p>\n<p>This morning I started with working on a <a href=\"\">HomeKit<\/a> application, only to take a detour to working with <a href=\"\">NSNotification<\/a>s in Swift.  I&#8217;m going to make the assumption that you are already familiar with both <code>NSNotification<\/code> and <code>NSNotificationCenter<\/code>.  I tend to use these a lot when programming applications that have a number of moving parts and threads.  I may be doing it <i>all wrong<\/i> and I&#8217;m sure there&#8217;s some pattern I&#8217;m missing out on, but the model of broadcasting events (notifications) to interested parties has served me well.<\/p>\n<p>Let&#8217;s look at the basic Swift method for getting a handle to the default notification center (I&#8217;m going to break my verbosity rule here and use <code>nc<\/code> as the variable name rather than <code>notificationCenter<\/code>):<\/p>\n<pre>\nlet nc = NSNotificationCenter.defaultCenter()\n<\/pre>\n<p>Simple enough.  Now, I want to register my object (typically a view controller) for receiving a notification.<\/p>\n<pre>\nnc.addObserver(self, selector: \"addHomeError\", name: kAddHomeError, object: nil)\n<\/pre>\n<p>In plain English, I&#8217;m telling the notification center to call <i>my function<\/i> <code>addHomeError<\/code> whenever someone posts a <code>kAddHomeError<\/code> notification.  <code>self<\/code> is the object to call and <code>addHomeError<\/code> is the function.  Notice that the Objective-C <code>@selector()<\/code> construct is gone in favor of naming the function as a string.  And of course <code>kAddHomeError<\/code> is simply a constant string defined somewhere else.  In this case the definition is <code>let kAddHomeError = \"AddHomeError\"<\/code>.<\/p>\n<p>In another object I can post my notification with:<\/p>\n<pre>\nnc.postNotificationName(kAddHomeError, object: nil)\n<\/pre>\n<p>Since my first object registered to receive a notification when <code>kAddHomeError<\/code> was posted, its <code>addHomeError<\/code> function will be called.<\/p>\n<p>In both cases I&#8217;ve left the <code>object<\/code> parameter <code>nil<\/code>.  This parameter is applicable only if you want to distinguish between separate objects registering and posting notifications.  When specifying <code>nil<\/code> in the <code>addObserver<\/code> function you are saying, &#8220;Hey, I don&#8217;t care <i>who<\/i> posts this notification, send it to me.&#8221;  If you provide an object to the <code>object<\/code> parameter you are making a statement, &#8220;I&#8217;m only interested in notifications from this specific object.&#8221;<\/p>\n<p>In the above example our function we want called is <code>addHomeError<\/code>, so we need to write it:<\/p>\n<pre>\nfunc addHomeError() -> Void {\n  var alert = UIAlertController(title: \"HomeKit Wizard\", message: \"Unable to add home\", preferredStyle: UIAlertControllerStyle.Alert)\n  alert.addAction(UIAlertAction(title: \"OK\", style: UIAlertActionStyle.Default, handler: nil))\n  self.presentViewController(alert, animated: true, completion: nil)\n}\n<\/pre>\n<p>Given that I&#8217;m calling <code>presentViewController<\/code> in our function, it&#8217;s a safe bet to assume that I&#8217;m handling receipt of the notification in a view controller.  So our notification comes from one object, and is handled in a view controller.  Straightforward.  What I don&#8217;t like though is the error message is <i>Unable to add home<\/i>.  It would be nicer if the dialog indicated the name of the home it couldn&#8217;t add.<\/p>\n<p>We can accomplish that through the use of the <code>userInfo<\/code> parameter when calling <code>postNotificationName<\/code>.  It took a minute to figure out the function signature, because quite frankly it looks a little, well, <a href=\"https:\/\/developer.apple.com\/library\/prerelease\/ios\/documentation\/Cocoa\/Reference\/Foundation\/Classes\/NSNotificationCenter_Class\/index.html#\/\/apple_ref\/occ\/instm\/NSNotificationCenter\/postNotificationName:object:userInfo:\">non-obvious<\/a>.  Let&#8217;s take a look.<\/p>\n<pre>\nfunc postNotificationName(_ notificationName: String,\n                   object notificationSender: AnyObject?,\n                 userInfo userInfo: [NSObject : AnyObject]?)\n<\/pre>\n<p>Perhaps you&#8217;re a quicker study than I am, but&#8230;  <code>[NSObject : AnyObject]?<\/code>.  Huh? What? (No pun intended.)<\/p>\n<p>A glance back at the Objective-C signature for <code>postNotificationName<\/code> and the lightbulb went off.  Or at least started glowing a little.  The <code>userInfo<\/code> parameter in Objective-C is an <code>NSDictionary<\/code> and it stands to reason Swift would be no different.  And it isn&#8217;t.  The signature syntax just looks strange.  Seriously though, all you need to do is pass in a dictionary where the keys are derived from <code>NSObject<\/code> and the values are <code>AnyObject<\/code>.  The question mark is just there to signify that this parameter <i>could be nil<\/i>.<\/p>\n<p>Unlike earlier versions of Objective-C (<code>[NSDictionary dictionaryWithObjectsAndKeys:]<\/code> anyone?), Swift comes out of the box with so-called &#8220;literal dictionaries,&#8221; a construct that other languages such as Python and Ruby call just <i>dictionaries<\/i>.  So we don&#8217;t have to do any special dictionary-building to use <code>userInfo<\/code>.  Our error notification can now be transformed into:<\/p>\n<pre>\nnc.postNotificationName(kAddHomeError,\n                        object:nil,\n                        userInfo:[\"message\":\"Unable to add \\(homeName) Home\"])\n<\/pre>\n<p>We don&#8217;t have to limit ourself to a single-entry dictionary either:<\/p>\n<pre>\nnc.postNotificationName(kAddHomeError, \n                        object:nil,\n                        userInfo:[\"message\":\"Unable to add \\(homeName) Home\",\n                                  \"details\":e.localizedDescription])\n<\/pre>\n<p>Now, let&#8217;s handle our notification.  The first thing we need to do is update our function to be passed the notification object which contains our <code>userInfo<\/code>.  Recall the first version of the function had <i>no arguments<\/i>, that is, we didn&#8217;t care about the <code>NSNotification<\/code> object itself.<\/p>\n<p>Our method signature becomes <code>func addHomeError(notification:NSNotification)<\/code>.  If we made this change now and ran our application it would most surely crash.  Why?  Because of this right here: <code><br \/>\nnc.addObserver(self, selector: \"<b>addHomeError<\/b>\", name: kAddHomeError, object: nil)<\/code>.  That selector definition indicates a function named <code>addHomeError<\/code> which takes <i>no arguments<\/i>.  We don&#8217;t have that anymore, we take one argument.  So you&#8217;re in for a <code>unrecognized selector sent to instance<\/code> crash if you try that.  Update the selector to <code>addHomeError:<\/code>:<\/p>\n<pre>\nnc.addObserver(self, selector: \"addHomeError:\", name: kAddHomeError, object: nil)\n<\/pre>\n<p><i>Finally<\/i>, in our <code>addHomeError<\/code> function, let&#8217;s unwrap our <code>userInfo<\/code> dictionary and message.<\/p>\n<pre>\n  func addHomeError(notification:NSNotification) {\n    \n    let userInfo:Dictionary<String,String!> = notification.userInfo as Dictionary<String,String!>\n    let messageString = userInfo[\"message\"]\n    \n    var alert = UIAlertController(title: \"HomeKit Wizard\", message: messageString, preferredStyle: UIAlertControllerStyle.Alert)\n    alert.addAction(UIAlertAction(title: \"OK\", style: UIAlertActionStyle.Default, handler: nil))\n    self.presentViewController(alert, animated: true, completion: nil)\n  }\n<\/pre>\n<p>Now perhaps there&#8217;s an easier way to do this, but, when receiving the <code>userInfo<\/code>, the routine handling the notification doesn&#8217;t know what type of dictionary is there.  Recall that the only requirement was that it be of type <code>[NSObject : AnyObject]?<\/code>.  So our code has to be a bit more explicit as what we know the dictionary to be, and that is of type <code>[String : String!]<\/code>.  Once we&#8217;ve set the compiler straight, we obtain our <code>messageString<\/code> and supply it to our <code>UIAlertController<\/code>.<\/p>\n<p>Now we get a nice error message:<\/p>\n<p><a href=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/08\/image1.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/08\/image1.png\" alt=\"image1\" width=\"320\" height=\"568\" class=\"alignnone size-full wp-image-553\" \/><\/a><\/p>\n<p>With that out of the way I can get back to our upcoming article on HomeKit.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Update 9\/18\/16: Swift 3.0 has brough even more changes to working with notifications and userInfo; come visit our new article on handling Notifications with Swift 3.0 Update: Swift 2.2 has brought a number of changes; come visit our new article on handling NSNotification userInfo in Swift. I frequently sit down intent on writing about one [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11,15,5],"tags":[],"class_list":["post-544","post","type-post","status-publish","format-standard","hentry","category-apple","category-homekit","category-swift"],"_links":{"self":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/544"}],"collection":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/comments?post=544"}],"version-history":[{"count":25,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/544\/revisions"}],"predecessor-version":[{"id":2804,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/544\/revisions\/2804"}],"wp:attachment":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/media?parent=544"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/categories?post=544"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/tags?post=544"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}