The World’s Leading Microsoft .NET Magazine
   
 
The .NET Addict's Blog

My Top Tags

                                                           

My RSS Feeds








Latest Diggs - Programming

Internet Blogs - Blog Top Sites

Site Hits

Total: 2,639,104
since: 19 Jan 2005

Exploring the Delegate Design Pattern

posted Mon 14 May 07

When I first started learning Cocoa I ran across a design pattern that I had seen implemented a few times before but I had yet to see it labelled with a name. This pattern is called the Delegate design pattern. Coming from C#, I found this initially confusing because in C# the concept of a delegate is slightly different than the concept of a delegate in the Cocoa world. In C#, a delegate is essentially a function pointer, and when someone in Cocoa refers to a delegate, they are referring to an entire instance of a class to which work is delegated.

To see how this pattern works, I needed an example. So, the example I used was a control that is bound to an array of items. So, let's say you have a control that you want to render a list of customers. There are two really obvious approaches to this problem: data binding and the Delegate design pattern.

In data binding, the idea is that your controller will "stuff" the data into the view in some fashion. Often this involves cramming the entire result set into the view and letting the view deal with things like scrolling or paging. You can almost think of the Delegate design pattern as reverse data binding - the control asks the controller for the data it needs, and only the data it needs. The benefits here are that in some data binding scenarios, it becomes extremely easy to tie the view too closely to the controller - making it difficult to use the view for anything but a specific type of data. In addition, if you're not using something like the delegate design pattern, it also becomes easy to get inefficient and cram immense result sets into the control when you really only need to be working with a small window into the result set at any given time.

So, let's take a look at a quick sample. Assume that you're building a custom view in Cocoa called RadialLayoutView. This view lays out all of its subviews so that they are all arranged in a circle. Each of the subviews is actually a piece of data with a name and description. You could easily (especially if you're coming from the WPF world) data bind the control to an array of a custom type, say RadialNode or something. However, there is a way to make it so that your control only ever has to worry about those nodes that are on the screen at a given time, and it doesn't need to know anything about the underlying model that is supplying the name and description values.

The delegate is going to be a pointer to an object that will do the work required of the delegate. In this case, we're going to want to make a delegate that will provide the control with the count of all nodes in the system, and it will also provide the name and description of a single node. Whenever the control needs an item, it can simply ask the delegate for one. This provides a huge amount of power and flexibility and loose coupling between the view and the model that you don't normally find in standard databinding patterns.

To tell the application what the control demands of its delegate, we can use a protocol:

@protocol RadialLayoutDelegate
@required
  - (unsigned) countNodes;
  - (void) nodeAtIndex: (unsigned)index
                        name: (NSString **)outName
                 description: (NSString **)outDescription;
@end

Yes, there's some Leopard syntax here, but it's stuff that you can find elsewhere so there's no NDA problem. With the protocol in mind, we can define (in the .h file) our custom view as:

@interface RadialLayoutView
{
     IBOutlet id<RadialLayoutDelegate> delegate;
}
@end

You may notice some similarity between .NET Interfaces and Cocoa protocols. That, of course, is because they both serve the same purpose - they define a set of constraints to which any object implementing said interface (or protocol) must conform. The difference is that you can have pieces of a protocol be optional using the @optional keyword, whereas in .NET if you implement an interface, you must implement all of it or suffer the consequences.

Now, I can write code inside the custom view that just invokes methods on the delegate in order to get the data it needs in order to create and render its list of subviews. For example, to get the name and description of the root node in the data set:

NSString *rootName;
NSString *rootDescription;

[delegate nodeAtIndex:0 name:&rootName description:&rootDescription];

That's all there is to it. The nodeAtIndex method coupled with the countNodes method are all that's needed to give the control the ability to render a near-infinite amount of data because it doesn't have to maintain it all at once, and the delegate can be fetching that data from XML, from memory, or from Core Data - the view doesn't care.

In short, using the delegate design pattern (in Cocoa or in WPF, for that matter) gives me a level of flexibility and agility that I don't normally see with desktop applications. I'm finding that there are a lot of things that I can do elegantly, simply, and quickly using this pattern that I found tedious or cumbersome using traditional data binding.

tags:            

links: digg this    del.icio.us    technorati    reddit




1. Jeff LaMarche left...
Tue 15 May 07 7:29 am

Nice series of articles. It's great to see a programmer who is open-minded about other environments. Many of us get comfortable with one or a few languages and environments and sort of shut down when challenged with something different. It's fun watching someone else go through the same process with Cocoa - it's a fascinating toolset once you wrap your head around it. It's not perfect, and I certainly wish that Apple would add some of the spit and polish and developer features that Visual Studio has, but overall, Cocoa is one of the few truly enjoyable ways to build an application.


2. Kevin Hoffman left...
Tue 15 May 07 7:31 am

Thanks Jeff. I find that by exploring everything around me, instead of becoming myopic about my current toolset, I can grow as a person and as a developer. Learning Cocoa has made me a better Vista programmer, as well as truly appreciate the pleasure I get from writing Cocoa applications.


3. Shawn Erickson left...
Tue 15 May 07 11:18 am

Often delegate protocols in Cocoa are informal protocols (aka the delegate can implement an arbitrary subset of the full protocol). This allows the delegate to influence only the aspects of the delegate contract that it needs. The delegating object in its various pathways first checks if its delegate responds to the particular delegate message and if it does calls the delegate giving the delegate a chance to modify the behavior of the delegating object. This allows a delegate to modify the behavior of another object without forcing the use of a subclass, etc.

Another common form of the delegate pattern in Cocoa are data sources (this is closer to what you outlined in this blog article). These are also often informal protocols but often the data source object (aka delegate) must implement a certain subset of the full protocol. This type of delegate pattern is most often used by view objects to fetch the data that they are being asked to display. As a result a certain subset must be implemented so the view can carry out the basic display task. However the data source can implement more of the data source protocol to add support for things like drag and drop, data mutation, etc.


4. Jamie left...
Tue 15 May 07 3:09 pm

Kevin, thank you for writing this series of great articles. Knowing Cocoa has made me a more proficient .Net programmer (my day job) and I am glad someone is sharing their similar experience. Hopefully, some crossbreeding will push both frameworks and software forward to new heights.


5. Kevin Hoffman left...
Wed 16 May 07 6:35 am

Shawn - thanks so much for the comment. I love it when the Cocoa experts drop by and leave little nuggets of enlightenment :)


6. Paolo left...
Wed 16 May 07 8:37 am :: http://cocoadhoc.blogspot.com

Related to what Shawn was commenting, I've to add that among us, people coming from pre-Bindings Cocoa, it was usual the definition of Categories to give common structures (like NSArray) the capability to be simple data sources themselves (thus a sort of delegate) for a number of common views (NSComboBoxes, NSTableViews, ...). Sometimes, I still prefer that approach, as it is more traceable while debugging than Bindings.


7. Shawn Erickson left...
Wed 16 May 07 10:10 am

Kevin, it is nice to see your articles on this, thanks for taking the time to write them.

I am a strong believer that by learning multiple programming paradigms, frameworks and languages you gain insights that can help you in your development environment/platform of choice (or at least the one required by your job).


8. Kevin Hoffman left...
Wed 16 May 07 10:26 am

I couldn't agree more. The more alternative ways you discover to accomplish the same task, the better you become at that task and similar tasks. My exploration of Cocoa has made me a better .NET programmer.


9. Victor K. left...
Thu 17 May 07 9:33 am

A well explained example for numerical array data sources for NSTableView is NumericalArrayDS, http://turin.nss.udel.edu/programming . And for some further hints & tips on how to get delegates do what you want check out htt p://www.dribin.org/dave/blog/archives/2007/01/25/objc_delegate_optimization _2 . Very interestings reads as well ....


Tag Related Posts

So I'm in the LA Times ;)

Wed 27 Aug 08 2:51 P GMT-05
tags:                  

MobileMe vs. Live Mesh Throwdown - Round 1

Wed 16 Jul 08 10:33 A GMT-05

Building Model Classes in C# and Cocoa

Sun 15 Jun 08 3:13 P GMT-05
tags:            

MobileMe vs. Live Mesh - Round 1

Wed 11 Jun 08 12:20 A GMT-05

My Macbook Air is masculine, dammit!

Mon 17 Mar 08 6:59 P GMT-05
tags:          

iPhone Underrated as a Gaming Device?

Fri 14 Mar 08 1:50 P GMT-05
tags:        

My take on the iPhone SDK

Sat 08 Mar 08 1:39 P GMT-05

Jobs says "not likely" to Flash on the iPhone

Thu 06 Mar 08 1:39 A GMT-05
tags:          

My Macbook Air Review

Sun 02 Mar 08 4:20 P GMT-05

iPhone Roadmap March 6th

Fri 29 Feb 08 10:41 P GMT-05
tags:        

Video of the Macbook Air in Action

Wed 20 Feb 08 3:04 P GMT-05

Macbook Airはきれいですよ!

Sun 17 Feb 08 2:38 A GMT-05

Why is O'Reilly Condoning iPhone Hacking?

Mon 11 Feb 08 3:55 P GMT-05

Evaluating my next laptop purchase

Wed 06 Feb 08 8:40 P GMT-05

The iPhone SDK key has been leaked! Oh Noez!!!1

Tue 29 Jan 08 11:36 A GMT-05
tags:        

Why Geeks just don't "get" the Macbook Air

Thu 17 Jan 08 2:30 P GMT-05

Popcorn + TiVo + Macbook Pro + iPhone == Hell Yeah!

Tue 15 Jan 08 3:11 P GMT-05
tags:          

CLINQ v1 Demo - Network Message Filtering

Wed 09 Jan 08 7:47 P GMT-05
tags:        

How my ADC membership changed my life

Mon 31 Dec 07 3:57 P GMT-05
tags:      

Leopard Code Sample : Sprinkling in some Bonjour

Tue 27 Nov 07 2:32 P GMT-05
tags:        

Leopard Sample: A Bound NSCollectionView

Mon 29 Oct 07 1:41 A GMT-05

Leopard is out - let the code samples begin!

Fri 26 Oct 07 10:09 A GMT-05
tags:          

My life is complete : iPhone SDK is CONFIRMED.

Wed 17 Oct 07 6:38 P GMT-05
tags:          

Leopard Shipping October 26th!!

Tue 16 Oct 07 4:59 P GMT-05
tags:        

Building a Ledger Style for WPF Grids

Tue 21 Aug 07 3:30 P GMT-05
tags:    

My iPhone Review

Mon 23 Jul 07 1:09 P GMT-05
tags:        

Microsoft Codename Acropolis - Unwrapped

Wed 20 Jun 07 3:22 P GMT-05
tags:              

The dreaded language bleed-over has begun

Tue 19 Jun 07 6:23 P GMT-05
tags:        

My first "Acropolis" Application

Mon 04 Jun 07 1:40 P GMT-05
tags:      

Exploring the Delegate Design Pattern

Mon 14 May 07 6:30 P GMT-05

Core Data - Almost too Easy?

Wed 18 Apr 07 2:23 P GMT-05

Will Silverlight be DOA?

Mon 16 Apr 07 8:02 P GMT-05

Exploring the MVC Pattern in WPF

Tue 10 Apr 07 12:51 P GMT-05
tags: