Sheni
Sheni

Reputation: 129

Is setting a pointer from a singleton to a viewController and updating GUI a violation of MVC

I'd like to ask a theoretical question pertaining to good code practice and the MVC model, Here is the case:

The design contains a RootViewController and a singleton class. The singleton acts as a controller with a timer objects that should be available throughout the app. The timer object consists of a UISwitch and an NSTimer, they are both owned by the singleton controller so the UISwitch can be added to new viewControllers on demand and the timer object is accessible throughout the app.

In order to update the RootViewController's screen with the current timer's count i created a pointer in the singleton to the RootViewController and have the RootViewController set itself to that pointer, similar to [singeltonOBject setDelegate:self]. Using this design the UILabel of the RootViewController can be accessed and updated from the singleton when the timer ticks. I chose to do that because i didn't have time to implement a regular delegate.

Note that the RootViewController is owned by the AppDelegate and the the singleton class is obviously NOT owned by the RootViewController. Therefore there is no retain cycle.

Question: Is the setting of a pointer from the singleton to the RootViewController and updating the UILable from the singleton controller a violation of good coding practice, are there any basic principles that are not fulfilled?

Thanks for your answer!

Upvotes: 1

Views: 143

Answers (1)

Ben Trengrove
Ben Trengrove

Reputation: 8729

Problem

Generally when something doesn't feel quite right, thats because it's not.

While your code will work it is not going to be easy to maintain in the future and is liable to breaking. Even if you never plan on looking at this code again, it is always good to practice good coding conventions.

I recommend reading The Pragmatic Programmer which contains lots of tips for programmers on how to write better code. One of those tips is Minimize Coupling Between Modules. Right now your RootViewController knows about your Singleton and your Singleton knows about your RootViewController so they are both coupled to each other. In the future, when you change one you are likely to have to change the other one as well.

What if you want to add another label? You will have to add the label in the RootViewController and then change your singleton to update that label as well.

What if you remove the label altogether? Lets say you go back to this in a years time and remove the label, suddenly there is another class that is not compiling and you might not remember why. You have broken code in a completely separate part of your application.

As for following MVC, this is in violation of that. Your view is being modified by something separate. If MVC is setup correctly you should be able to put on as many views as you want without having to change any code that is controlling data, in this case your timer.

Now as for memory management, your RootViewController is now being retained by this Singleton. Singleton's exist for the entire life of an application. You are right that you do not technically have a retain cycle however your RootViewController will now never be deallocated. In most applications this does not matter as the RootViewController always remains at the bottom of the stack but it is a coincidence and thus cannot be reliably programmed on. This is actually another tip from The Pragmatic Programmer, Don’t Program by Coincidence.

Solution

A better solution would be to use a notifications if you really need a global timer like you say (another story is that your global timer singleton does not sound like a good idea). Whenever you were updating your label from within your singleton you can fire a notification instead. Your RootViewController will receive this notification and can update its label. You can pass data in a notification if needs be. Now in the future if you make a change to the view and want to update something else you only need to change code in one location (The RootViewController).

Upvotes: 5

Related Questions