by Ryan Green
Today we explore the emerging zeitgeist of two companies that I love. I submit to you that embedded in the very code of their developer SDKs lie the underpinnings to a complete corporate world view. I know, profound stuff. I thought so myself while typing this in the airline terminal of Denver International Airport while waiting for a friend to arrive. Perhaps I’ve waited too long and those funnel cake sticks from that other burger chain have started to affect my brain chemistry. We shall see.
My new working theory is derived by examining the use of patterns in the User Interface components of Cocoa and Flex.
Exhibit A: Apple believes the world and developers must be controlled and well managed. This is why the primary pattern for talking to User Interface (UI) Components is the delegate pattern. The delegate pattern means that when a user does something to a component, like clicking on a Picker, that Picker UI Component delegates responsibility to a delegat-ee. In other words, the Picker tells the delegate what to do and when to do it. There are a few benefits to the use of this pattern. Delegates clean up well (memory-wise), delegates have a clear and predictable function, and there is one and only one responder for any action by a UI component.
Exhibit B: Adobe loves freedom loving developers and puppies and believes in letting the garbage collector take care of cleaning up after both. The observer pattern means that when the user performs an action such as clicking on a Combobox (Picker) Component, rather than telling a delegate what to do, the Combobox notifies the world that the click happened. What the world chooses to do with this information is up to the “people” who live in it. The benefits of this pattern include the ability for multiple observers to react to a single UI event. There is generally looser coupling between a “View” and “Controller” in an Model-View-Controller pattern. The downside of this pattern in Flex is that listeners are generally not “weak” references, which can lead to memory leaks if not cleaned up properly.
Delegating Responsibility
As a Cocoa developer you are most likely familiar with the delegate pattern. In our example, we will look at the UIPickerView Class in Cocoa.
The UIPickerView has a property called “delegate” which accepts a reference to a class that adheres to the UIPickerViewDelegate Protocol. When a user selects an item from the picker, the UIPickerView looks at the delegate it has been given and asks the delegate if it implements the pickerView:didSelectRow:inComponent instance method. If it does, then the UIPickerView delegates responsibility to act on the row selection by invoking the instance method on the delegate. Perhaps the picker is displaying a list of pages. The delegate might take the url of the current picker selection and load a UIWebView to display its contents.
A more generic model of the Delegate Pattern is displayed in figure 1.1.
Figure 1.1
Now, a delegate class may be interested in the actions a user takes on one view, or possibly multiple views of different types. Perhaps you have created a delegate to examine the contents of a UIView with two UITextInput instances and a UIPickerView instance. A delegate may implement the UIScrollViewDelegate, the UIPickerViewDelegate and the UITextInputDelegate . The UI Component which receives the user action may then invoke the property instance method on the delegate based on its documented protocol.
On notifying those who care…
I use this example so that we can examine the differences between the delegation pattern most often used by UIKit elements in Cocoa and the observer pattern most often used with UI Controls in the Flex framework.
An Observer pattern is one in which an “Observer” registers itself with a “Notifier”, or in the Flex case, an “EventDispatcher” The Observer tells the EventDispatcher which types of events it wishes to be notified about. Many Observers may listen for events on a single EventDispatcher instance. (as Illustrated in Figure 1.2) This is different than the delegation pattern. Generally, only one delegate may be set on a Cocoa UI Component at a given time.
Figure 1.2
In Figure 1.2 we see that when an action is completed in a View, the view dispatches an Event. This dispatchEvent(event:Event); instance method, finds all Observers which have registered to be notified of that action and invokes the instance method the Observer provided.
Figure 1.3
To illustrate this in Flex, let’s use the <mx:ComboBox /> component. This component is similar to a UIPickerView in that it displays a list of options to choose from and then dispatches an event when a user selects an item from the list.
Observers in Flex may be set in a few different ways. In MXML, an observer may look like this:
<mx:Canvas xmlns:mx="library://ns.adobe.com/flex/mx"> <mx:Script>
<![CDATA[
import mx.events.ListEvent;
public function handleChange(event:ListEvent):void {
}
]]>
</mx:Script>
<mx:ComboBox change="handleChange(event);" />
</mx:Canvas>
Another way of declaring an observer is through actionscript.
package
{
import mx.containers.Canvas;
import mx.controls.ComboBox;
import mx.events.ListEvent;
public class MyCanvas extends Canvas {
public function MyCanvas():void { super(); }
public var delegate:Object;
override protected function createChildren():void {
super.createChildren();
var cbo:ComboBox = new ComboBox();
if(delegate.hasOwnProperty('handleChange')) {
cbo.addEventListener(ListEvent.CHANGE,delegate.handleChange);
}
addChild(cbo);
} } }
What Happened?
In most cases, the contents of the Event object should be able to tell you everything you need to know about the action that took place. In a ListEvent.CHANGE event, the event.currentTarget property tells you which UI component the action originated from, the event.rowIndex property tells you which item in the list was selected, and the event.itemRenderer.data property gives a reference to the source data for the selected item in the list.
Conclusion
No framework has a monopoly on patterns. You will find observer and delegate patterns sprinkled throughout both SDKs. As you can see from the previous code example, it is possible to adapt Flex to follow more of Cocoa-like style of UI control. I would encourage you to make friends with the Flex observer pattern implementation. It is the primary driver for Flex UI component interaction. You can find more information about Flex observers here.
But the thinking behind each pattern is profoundly different and both philosophies can be seen poking out in public statements by each company. When Apple says that 3rd party crodd-platform development tools are unwelcome on the iThings they cite the desire to promote high quality apps, as defined by their own vision of good code. Adobe, on the other hand, has repeatedly spoken about their commitment to a framework that is as open ended as possible. Neither framework is “right” – both have pros and cons – but for a developer trying to make the shift from one to the other, the differences need to be understood at the foundational level as a difference of philosophy, not simply syntax.
—————
This article was first published on the Intel AppDeveloper site here: http://appdeveloper.intel.com/en-us/article/porting-iphone-netbook-flex-interacting-ui-cocoa-delegates-and-flex-observers