{"id":13,"date":"2010-03-16T11:55:51","date_gmt":"2010-03-16T19:55:51","guid":{"rendered":"http:\/\/bynomial.com\/blog\/?p=13"},"modified":"2010-04-24T15:42:09","modified_gmt":"2010-04-24T23:42:09","slug":"callbacks","status":"publish","type":"post","link":"http:\/\/bynomial.com\/blog\/?p=13","title":{"rendered":"Callbacks"},"content":{"rendered":"<p>In this post, I&#8217;ll enumerate four major types of callback mechanisms in Objective-C, and mention some comparisons to help choose the best one for whichever class you&#8217;re designing.<\/p>\n<p>Intuitively, a callback is a method that you think of as being called from outside your code.<\/p>\n<p>More formally, a callback is a method that can be called by other classes which may be created after, or independently of, your class. \u00c2\u00a0These methods are named callbacks because we have to explicitly provide a pointer to the caller so they can &#8220;call us back&#8221; later. \u00c2\u00a0Two classic examples: an asynchronous NSURLConnection needs a way to report back when it&#8217;s done loading a page, and a UIButton needs a way to report that a user pressed the button.<\/p>\n<h1>Types of Callbacks<\/h1>\n<h2>Delegation or Formal Protocols<\/h2>\n<p>Delegation is one of the most common callback mechanisms in current Objective-C code. \u00c2\u00a0The use of formal protocols (or just &#8220;protocols&#8221; in the language spec) is almost\u00c2\u00a0synonymous\u00c2\u00a0with delegates, so I&#8217;ll group them together here; although you can use protocols for non-delegate purposes, too.<\/p>\n<p>To use this method, you declare a set of methods in a @protocol block, and require the class getting called back to be set as your delegate object \u00e2\u20ac\u201c generally this is a weak reference (not retained) to an id&lt;MyClassDelegate&gt; type. \u00c2\u00a0When you want to call the callback, you can simple execute a [delegate doMyCallbackWithObject:x] statement on required methods. \u00c2\u00a0For optional methods, first check that they&#8217;re implemented, and either call them or execute your default behavior.<\/p>\n<p>UITableViewDelegate is a good example protocol for this callback mechanism.<\/p>\n<h2>Target\/Action Pairs<\/h2>\n<p>UIControl and therefore its subclasses \u00e2\u20ac\u201c including UIButton, UISwitch, and UISlider, to name a few \u00e2\u20ac\u201c all use a target\/action pair method to handle callbacks.<\/p>\n<p>To use this method, the class getting called back must specify both a selector (the <em>action<\/em>) and an object pointer (the <em>target<\/em>) that you can call at any time. \u00c2\u00a0It is up to the target to make sure the signature (i.e. the set of input and output parameters) of the action is something useful to your class. \u00c2\u00a0Notice that each selector has to be registered separately, as opposed to the delegate method which registers all the callbacks in one set.<\/p>\n<h2>Informal Protocols or Category Callbacks<\/h2>\n<p>Objective-C didn&#8217;t always have the @optional keyword for @protocols, which makes delegation very practical. \u00c2\u00a0Before @optional, it was common to add a category to NSObject which implemented the callbacks you needed \u00e2\u20ac\u201c this is an informal protocol. \u00c2\u00a0This is similar to a formal callback in that all the names and signatures of the methods are fixed and available in a header file, but it differs in that all objects necessarily have a default implementation (no required or optional distinction) and a class can&#8217;t officially declare that it overrides these methods (but we can still find out at runtime of course).<\/p>\n<p>Apple is phasing out informal protocols in favor of formal ones, although they can still be useful in situations where you&#8217;d prefer all objects to have easy access to default implementation of the protocol.<\/p>\n<p>NSURLConnection is an example of an informal protocol callback mechanism.<\/p>\n<h2>Notifications<\/h2>\n<p>Notifications are ideal for broadcasting messages (one-caller-to-many-callback-receivers) or for some decoupling of the caller and receiver.<\/p>\n<p>To use this method, the caller simply posts an NSNotification object to an NSNotificationCenter; any classes that are interested in being called from this must have previously registered themselves as an observer of that notification. \u00c2\u00a0Notifications are identified by strings, and there is no formal way to declare which notifications your code produces \u00e2\u20ac\u201c this communication must happen in comments\/documentation (or by hand-parsing the code if you have to).<\/p>\n<p>UIKeyboardWillShowNotification is an example notification name (it&#8217;s a string) that is posted when the keyboard is about to show up. \u00c2\u00a0This gives UI elements a chance to react by moving important views so they&#8217;re not obstructed by the keyboard.<\/p>\n<h1>Choosing a type of callback<\/h1>\n<p>Each approach has pros and cons. \u00c2\u00a0To help see this, consider the use cases for UITableViewDelegate (delegation), UIButton (target\/action), NSURLConnection (informal protocol), and UIKeyboardWillShowNotification (notification).<\/p>\n<p><strong>Delegation<\/strong> Pros: One object pointer connects all the methods, signatures and names of methods are clearly documented, required and optional method distinction. \u00c2\u00a0Cons: Impractical to be a delegate for multiple objects, subclassing the called back class is challenging.<\/p>\n<p><strong>Target\/Action<\/strong> Pros: Easy to work with multiple objects giving callbacks, flexible signatures, only one method at a time is required. \u00c2\u00a0Cons: Practical only for small sets of methods, signatures are not formally declared, receiver must unregister itself before it&#8217;s gone.<\/p>\n<p><strong>Informal Protocol<\/strong> Pros: Default implementation always available, possible to avoid specifying a target. \u00c2\u00a0Cons: No compile-time declaration of following an informal protocol, fills up the method namespace, no required\/optional distinction.<\/p>\n<p><strong>Notification<\/strong> Pros: There can easily be many targets, caller doesn&#8217;t need any pointers to targets, receiver and target can be created in any order. \u00c2\u00a0Cons: Input parameters must be packaged in a userInfo dictionary, notification names are not formally declared, receiver must unregister itself before it&#8217;s gone, slightly longer calling time due to indirection.<\/p>\n<p>How to choose?<\/p>\n<p>If you might have many callers for the same target (such as a custom UI control), then target\/action is probably good.<\/p>\n<p>If you might have many targets for a single caller, then a notification is probably good, although you could also handle this with target\/action if tighter coupling is preferred.<\/p>\n<p>If you expect a one-to-one pairing between caller and target, then a delegate is probably the way to go.<\/p>\n<p>Are there still times to use informal protocols? \u00c2\u00a0Some folks might say no, but I&#8217;ll argue against that.<\/p>\n<p><strong>A case for informal protocols<\/strong><\/p>\n<p>When would you like to use informal protocols? \u00c2\u00a0I suggest using them when you want to implement a simple asynchronous interface with optional callbacks for a universally usable piece of functionality.<\/p>\n<p>For example, suppose you&#8217;re writing a serialization method that uses Objective-C&#8217;s reflection to convert any class into a string (your own version of NSCoding, basically). \u00c2\u00a0You&#8217;d like to allow any object to be able to call:<\/p>\n<p>[self writeToURL:myURL];<\/p>\n<p>And have this work out. \u00c2\u00a0In this case, a category on NSObject is perfect. \u00c2\u00a0Now, suppose you want to give users a chance to react to an error asynchronously, but only if they want to. \u00c2\u00a0Then you could implement your own version of [NSObject writeToURLFailedWithError:(NSError *)error], which simply NSLogs the error, and allow users to override this method. \u00c2\u00a0This is nice because the user&#8217;s class never has to specify itself as a delegate or a target\/action \u00e2\u20ac\u201c you&#8217;re aware of both the target (since you have access to self in writeToURL:) and the action (since you name the selector in your category). \u00c2\u00a0In other words, we&#8217;ve just made using this functionality a little easier by using an informal protocol.<\/p>\n<h1>Resources<\/h1>\n<ol>\n<li><a href=\"http:\/\/developer.apple.com\/mac\/library\/documentation\/cocoa\/Conceptual\/CocoaFundamentals\/CommunicatingWithObjects\/CommunicateWithObjects.html#\/\/apple_ref\/doc\/uid\/TP40002974-CH7-SW18\">Cocoa Fundamentals Guide: Object Communications<\/a> \u00e2\u20ac\u201c The best general documentation for all this stuff.<\/li>\n<li><a href=\"http:\/\/developer.apple.com\/iphone\/library\/documentation\/General\/Conceptual\/DevPedia-CocoaCore\/Protocol.html\">A concise explanation of formal vs. informal protocols<\/a><\/li>\n<li><a href=\"http:\/\/developer.apple.com\/mac\/library\/documentation\/cocoa\/conceptual\/ObjectiveC\/Articles\/ocProtocols.html\">The Objective-C language spec for protocols<\/a><\/li>\n<li><a href=\"http:\/\/developer.apple.com\/iphone\/library\/documentation\/UIKit\/Reference\/UIControl_Class\/Reference\/Reference.html#\/\/apple_ref\/doc\/uid\/TP40006779-RH2-SW28\">The Target-Action Mechanism<\/a> \u00e2\u20ac\u201c part of the UIControl class reference<\/li>\n<li><a href=\"http:\/\/developer.apple.com\/iphone\/library\/documentation\/Cocoa\/Conceptual\/Notifications\/Introduction\/introNotifications.html\">Notification Programming Guide<\/a><\/li>\n<li><a href=\"http:\/\/developer.apple.com\/iphone\/library\/documentation\/Cocoa\/Reference\/Foundation\/Protocols\/NSKeyValueObserving_Protocol\/Reference\/Reference.html\">NSKeyValueObserving Protocol Reference<\/a> \u00e2\u20ac\u201c An example informal protocol, and can be used to essentially create yet another type of callback mechanism \u00e2\u20ac\u201c although, that&#8217;s a subject for another post.<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>In this post, I&#8217;ll enumerate four major types of callback mechanisms in Objective-C, and mention some comparisons to help choose the best one for whichever class you&#8217;re designing. Intuitively, a callback is a method that you think of as being called from outside your code. More formally, a callback is a method that can be [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_mi_skip_tracking":false},"categories":[7,6],"tags":[30,29,37,36],"_links":{"self":[{"href":"http:\/\/bynomial.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/13"}],"collection":[{"href":"http:\/\/bynomial.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/bynomial.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/bynomial.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/bynomial.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=13"}],"version-history":[{"count":0,"href":"http:\/\/bynomial.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/13\/revisions"}],"wp:attachment":[{"href":"http:\/\/bynomial.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=13"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/bynomial.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=13"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/bynomial.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=13"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}