Dec 19 2011

Fundamental iOS design patterns: SharedInstance (Singleton in Objective C)

Category: Objective-c and CocoaDavide Zanotti @ 5:11 am

Brief introduction

Singleton is one of the (if not THE) most commonly used/abused design pattern adopted in software development.
Basically it’s used to restrict the instantiation of a class to one object only that can be used safely across application architecture. Its implementation is pretty simple compared to other patterns and it’s very similar for the most of programming languages, but in Objective C it has a slightly different approach due to the lack of “normal constructor” that are instead replaced by alloc/init paradigm.

How it works in Objective C

In Objective C, we can speak more appropriately about the SharedInstance pattern rather than traditional Singleton.
This one is often used in Apple frameworks and differently from its twin brother, it does not explicitly forbid the instantiation of multiple class instances, but it simply provide a class method that will return a shared instance. During the first call to that method the instance will be allocated and the next calls will return the previously object created. So this is a sort of hybrid approach.
A common class that use this pattern is UIApplication which implements a sharedApplication method (which returns the current running application). Differently from Singleton which use getInstance(), in Objective C the corresponding method has not a fixed name but it should start with “shared” followed by the “type” of class (so for UIApplication is “sharedApplication” for MYAmazingManager will be “sharedManager“). Anyway there are several exceptions, for example NSFileManager has a “defaultManager” acting as a sharedInstance accessor that could be renamed “sharedManager“.

Pattern implementation

In my singleton implementations I simply call the accessor “sharedInstance“, in this way I can use a simple pre-compiler macro that automatically synthesize this methods for me.
Even implementation of this pattern may vary and personally I adopted one which is thread-safe and rely on CGD (Grand Central Dispatch), which is an affective C level API provided by Apple in order to handle concurrency.

The implementation of my sharedInstance method is the following (comments explain how it works):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
+ (id)sharedInstance
{
    // structure used to test whether the block has completed or not
    static dispatch_once_t p = 0;
   
    // initialize sharedObject as nil (first call only)
    __strong static id _sharedObject = nil;
   
    // executes a block object once and only once for the lifetime of an application
    dispatch_once(&p, ^{
        _sharedObject = [[self alloc] init];
    });
   
    // returns the same object each time
    return _sharedObject;
}

Pattern in action!

SharedInstance pattern is IMO the best way to share data across multiple viewControllers in iOS applications.
One practical example is a data manager to share Core Data stuff such managed object context. I realized my own manager so that I can access this objects anywhere with ease like:

1
[[MYDataManager sharedInstance] managedObjectContext];

Tags: , ,


Mar 30 2009

ArrayCollection: filterFuntion with multiple filter functions using decorator pattern

Category: flexDavide Zanotti @ 3:21 am

I was looking for an elegant solution to implement multiple filter functions on an ArrayCollection (which provides a method filterFunction() that can be assigned dynamically in order to filter data inside the collection). The first and only valid solution I found was that one from Cristian Rotundu, he has extended ArrayCollection class providing a filterFunctions properties which accepts an Array of functions which will be executed in sequence (into a loop) once filterFunction is triggered. Anyway I didn’t want to subclass ArrayCollection and by using the decorator pattern I implemented my own multiple filters version.

So, this is what I done:

  1. I defined an interface IFilter, which declares only one method: apply()
  2. I defined a dummy Filter class (which implements IFilter in a basic way just to agree to the interface), that is used as a basic empty filter to decorate. It also has a constant called ALL_VALUES which is used as a wildcard for filters (it’s a simple string with value “*”, which means “all values are allowed”)
  3. I defined an abstract AbstractFilterDecorator class
  4. I created as many subclass of AbstractFilterDecorator as the filters I need (yes I treat filters as classes not mere functions)

The implementation code is the following:

1
2
3
4
5
6
7
8
9
var data:ArrayCollection = ArrayCollection(grid.dataProvider);
var filter:IFilter = new Filter();
               
filter = new LevelFilter(filter, levelValue);
filter = new CategoryFilter(filter, categoryValue);
filter = new DateFilter(filter, dateValue, "DD/MM/YY");
               
data.filterFunction = filter.apply;
data.refresh();

The filter object is wrapped by decorators which all accepts 2 common arguments: an IFilter reference and an Object representing a value. The DateFilter has a third parameter which is used to configure an internal DateFormatter (from mx.formatters package).
I’m pretty satisfied :)
Uh… and if you are worried about performance, it is fast enough because filter object are created once and then the function assigned to filterFunction is a reference to the resulting decorated filter.

UPDATE:
I realized a very simple example application which can be downloaded here.
This following is the content of the mxml file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">

    <mx:Script>
        <![CDATA[
       
            import mx.collections.ArrayCollection;
            import com.daveoncode.filters.*;
           
            private function applyFilters():void {
               
                var data:ArrayCollection  = ArrayCollection(userGrid.dataProvider);
                var filter:IFilter = new Filter();
               
                filter = new AgeFilter(filter, ageFilterValue.text);
                filter = new DateFilter(filter, dateFilterValue.selectedDate);
                filter = new SexFilter(filter, sexFilterValue.value);
               
                data.filterFunction = filter.apply;
                data.refresh();
               
            }
           
        ]]>
    </mx:Script>
   
    <mx:Panel title="Filters" width="600">
        <mx:Form>
            <mx:FormItem label="Age:">
                <mx:TextInput id="ageFilterValue" width="30" />
            </mx:FormItem>
            <mx:FormItem label="Sex:">
                <mx:ComboBox id="sexFilterValue" dataProvider="{[{data: Filter.ALL_VALUES, label: 'ALL'}, {data: 'm', label: 'Male'}, {data: 'f', label: 'Female'}]}" />
            </mx:FormItem>
            <mx:FormItem label="Join date:">
                <mx:DateField id="dateFilterValue" formatString="DD/MM/YY" />
            </mx:FormItem>
            <mx:FormItem>
                <mx:Button label="Apply filters" click="{this.applyFilters()}" />
            </mx:FormItem>
        </mx:Form>
    </mx:Panel>
   
    <mx:Panel title="Users" width="600">
        <mx:DataGrid id="userGrid" width="100%">
            <mx:dataProvider>
                <mx:ArrayCollection>
                    <mx:Array>
                        <mx:Object age="24" sex="f" name="Susan" joinDate="{new Date(2007, 5, 15)}" />
                        <mx:Object age="36" sex="f" name="Ashley" joinDate="{new Date(1998, 7, 20)}" />
                        <mx:Object age="24" sex="f" name="Jennifer" joinDate="{new Date(2001, 3, 24)}" />
                        <mx:Object age="19" sex="f" name="Emma" joinDate="{new Date(2002, 3, 24)}" />
                        <mx:Object age="44" sex="f" name="Carol" joinDate="{new Date(1999, 9, 16)}" />
                        <mx:Object age="28" sex="m" name="Peter" joinDate="{new Date(2005, 3, 12)}" />
                        <mx:Object age="35" sex="m" name="Mike" joinDate="{new Date(2008, 10, 10)}" />
                        <mx:Object age="26" sex="m" name="Dave" joinDate="{new Date(2008, 10, 10)}" />
                        <mx:Object age="44" sex="m" name="William" joinDate="{new Date(2004, 9, 16)}" />
                        <mx:Object age="24" sex="m" name="Sean" joinDate="{new Date(2006, 3, 24)}" />
                    </mx:Array>
                </mx:ArrayCollection>
            </mx:dataProvider>
        </mx:DataGrid>
    </mx:Panel>
   
</mx:Application>

Tags: , , ,


Mar 30 2009

Learning design patterns with Actionscript 3: episode 2 – Decorator pattern

Category: actionscriptDavide Zanotti @ 2:21 am

The objective of the decorator pattern is to provide a way to add extra features and responsibilities to a class at runtime without to subclass it.

The classes diagram of this pattern is composed by an interface or an abstract class which will define the supertype of the class that will be extended (decorated) by one or more classes implementing the same interface and extending an abstract class which identify these as decorator classes.

Continue reading “Learning design patterns with Actionscript 3: episode 2 – Decorator pattern”

Tags: ,


Dec 28 2008

Learning design patterns with Actionscript 3: episode 1 – Singleton pattern

Category: actionscriptDavide Zanotti @ 3:22 pm

In these Christmas holidays I bought some new books, among them I purchased “Actionscript 3 design patterns” (written by William Sanders and Chandima Cumaranatunge) and I’m actually studying this one. I never faced before the world of design patterns (which is, for those that never heard about, a way to write code and solve problems by implementing tested strategies that will guarantee flexibility and extensibility), or better I knew what a design pattern is, but I’m trying to learn to use them for the first time.
Unfortunately the first thing I learned about implementing design patterns in Actionscript 3 is that for some stuff we have to use workarounds, because actually as3 doesn’t provides 2 little useful things: abstract classes (on which most of the patterns are based) and not public constructor (in Java we can declare a class constructor as private, in as3 we must declare it as public), anyway with some little efforts, we can do everything :-)

Continue reading “Learning design patterns with Actionscript 3: episode 1 – Singleton pattern”

Tags: , , , , ,