One dilema when writing an app is where to put variables that contain the data for the application. Traditional global variables are not a good place, and it becomes nigh on impossible to keep track of where those variables are being access from in the code, and in multi-threaded apps it would also be difficult to coordinate atomic access.
Many of the iPhone examples and tutorials show that data can be stored in the AppDelegate class, and then references passed to controllers as required. I find this somewhat messy and just creates issues with memory management, retain/release strategies and the like. My preference is to put the application data in a single coordinated class that uses accessors to read/write the values and to help coordinate and track activity. This could well be useful when it comes to debugging the application.
There is a full implementation of a Singleton which can be used, but there are arguments that in some instances (like Unit Testing) you would want to be able to allocate fresh instances of the singleton class. In that instance, I would choose not to implement the allocWithZone, retain, release, etc methods. As long as by convention you have the singleton accessor method, you are good to go.
To setup the singleton, right click on your Classes group in the project, and choose New File… Choose to create a new object based on [cci lang=”objc”]NSObject[/cci]. This will generate the .m and .h files. In the .h file, add an class method (+) as the accessor for the singleton instance.
[cc lang="objc" width="auto"] @interface MyApp : NSObject { // put instance vars here } + (MyApp *) singleton; // accessor for the singleton instance @end [/cc]
Then in the .m, provide the implementation of the accessor:
[cc lang="objc" width="auto"] + (MyApp *) singleton { static MyApp *instance; @synchronized(self) { if (!instance) { instance = [[MyApp alloc] init]; } } return instance; } [/cc]
Now, whereever you want to access the properties or methods of the singleton within the application code (controllers etc), you reference the singleton instance:
[cc lang="objc" width="auto"] [[MyApp singleton] doSomething]; [/cc]
The use of [cci lang=”objc”]@synchronized[/cci] provides atomic access (thread safe) to an object.
Once this principle is established, it would also be good practice to put all application logic within the singleton, rather than within the various controller code. One thing you stand to be doing alot of in iPhone applications is creating variants of the UI elements (portrait/landscape views or controllers, views for iPhone/iPad etc), and so by centralising the application logic, you can just provide hooks in the controllers. This should help to make application maintenance much easier.
Additionally, if you provide accessors (getters/setters) for the instance variables, it will be easy to add a breakpoint to your code for those occassions when you know something is being altered but you can’t figure out where without extensive debug tracing.
1 thought on “Application Wide Variables and Helpers: The Singleton”