How to maintain data across object instances in Objective-C? - iphone

I've had some experience developing for the iPhone but am entirely self taught and am trying to improve my practices. This is a question that is probably pretty introductory to programming.
What is the best way (or is it possible) to maintain instance variables with values that are common to all instances of an object? Is it possible to have the creation, modification, and checking of an object and its attributes happen in different places?
Say I have an object that keeps track of the number of times a user swipes the screen. Is it possible to, say, allocate that object in my AppDelegate, and then somehow increment the count variable of that object from different view controllers?
Is it possible to define an instance variable such that it is shared across all instances of the object to which it belongs? That would solve the problem.
So far, I've just made IVARs in my AppDelegate for the things like this that I've needed to keep track of and then just accessed them like this:
((MyAppDelegate *)[UIApplication sharedApplication].delegate).instanceVariable
but I don't know if that's a good practice or not. Probably not.
Maybe this is related to global variables or singletons. Or the prefix "shared" that appears above and I've seen in other places too. I'm just looking for advice or a direction to look. I hope this question makes sense and isn't too general.

I think the question(s) you are asking involve different practices for different situations. To share data among viewcontrollers is one question with a number of solutions, one of the better ones being to use a delegate for all the viewcontrollers.
If you want to have a Class manage all its own objects, even if the objects come and go, you could do one of two things:
Make the Class have a singleton, and keep track of allocations and deallocations in order to know when it should create and then dispose of itself (if needed). This is not a bad way to do it, although it may be more work.
Create a controller class that manages your other class of objects. A good example may be a class of views, controlled by a viewcontroller class.
Let's see what other people suggest.

Matt Gallagher had post a great article on exactly that problem. You can see it at Cocoa with Love.
However, on a multiple view controllers patterns as mahboudz said, delegations is preferred.

In C++ or Java (etc), what you'd be looking for is a "static instance variable", which is exactly what you describe: an instance variable that is shared by all instances of the class. Objective-C does not have such a beast, precisely, but you can use some normal C syntax to give you something very similar.
See the bottom of this page:
http://iosdevelopertips.com/objective-c/java-developers-guide-to-static-variables-in-objective-c.html
(Copy of the code there in case the page vanishes:)
#interface MyClass
{
// ...
}
+ (NSString *)myVar;
+ (void)setMyVar:(NSString *)newVa;
#end
#implementation MyClass
static NSString *myVar;
+ (NSString *)myVar { return myVar; }
+ (void)setMyVar:(NSString *)newVar { myVar = newVar; }
#end
In this case "myVar" is global to the .m file, but because it's marked "static" (this is a C trick), the compiler limits its visibility to only the .m file that it's in. (As with anything like this, keep your eye on multithreaded access if you use that.)
FWIW, if you're building something that generally needs to be robust, a singleton-like object that everybody shares is a good way to go; you get all the normal Obj-C goodness (mem management if you want it) if you do that.

I would look into using a singleton as a resource manager - maybe the resource manager part is not needed for you, but a singleton would greatly help you.

It is definitely bad practice to use keep everything in the app delegate and access it where needed.. at the very least it means code reuse becomes tricky. If you make a new app and want to use a view or control or part of the system, you'd have to also make sure your new app delegate implements all the right selectors and properties.
Also, as your app grows you'll inevitably find your app delegate gets bigger and messier and harder to deal with.
Debugging becomes a pain too as it's harder to work out exactly which pieces of code are involved in a particular problem.
What I do this is to sketch out which parts of the app actually need which pieces of information, and pass those into the ViewControllers as they are created.

Related

How bad is it for a UIView to hold information on the Model (Business Object)

This question is specific to iOS development.
Imagine you use UITableView and inside the UITableViewCells you show information regarding one or more of your application business objects through a bit more complex class that we'll call ComplexBOView.
Now you want to trigger a specific action when the user taps this view contained in your UITableCellView (the event can be triggered through a UITapGestureRecognizer)
Most of the time what is considered "best practice" is to use the tag property of the UIView to actually go back to your model and retrieve the correct business object.
This often is suitable but in some cases it can come very handy to hold a pointer to the business object used to built your ComplexBOView.
#interface ComplexBOView : UIView
{
UILabel* lblSummary;
// ....
UITapGestureRecognizer* tapGesture;
NSObject* businessObject_;
}
#property (nonatomic, readonly) UITapGestureRecognizer* tapGesture;
#property (nonatomic, assign) NSObject* businessObject;
The idea behind this, is to actually directly go back to the businessObject when the user tapped the view.
Two questions here
Is it really bad to have NSObject* information inside the UIView ?
Should this information be retained meaning the relationship between the view and the model becomes here much stronger (ownership of the view towards the object) ?
Thanks for your advice.
The general advice is
Views don't own data!
and it's a good advice. It can save you a lot of trouble in the long run. But what does own mean? If you look at a UIButton or a UILabel, the button has a title the label a text property. So they are holding some data, they have to - the alternative would have to have a delegate that is asked for the text every time they get drawn.
So what does that mean in your case? Well that depends. If your ComplexBOView is just generic view that is specifically designed to display your specific business object, it wouldn't be the worst to hold that object in a property of it (just my opinion).
Of course you loose the possibility to easily reuse that view with a different model, but maybe that isn't an option anyway, because it's so specific. Of course you could move all that code from the ComplexBOView to the controller. But as you said then you also have to maintain a connection between each model object and the appropriate view. (Btw. I wouldn't use the tag to do that, it's better to just use an `NSDictionary instead)
On the other hand Trausi and Michael do have valid points. If you break that "rule" this one time, you might get loose and break it on every other occasion and before you know it, you end up with lots of custom views each holding a reference to some part of your model. In the long run you might make changes to your model (maybe in ways you never expected in the first place - and trust me, that is going to happen more often than not) and then you have to go to every single subclass and adjust them. Of course if that model-specific code lives in your controller you also have to modify all of that, but at least it's all in one place.
So to sum up, those best practices, advice and design patterns are there for a good reason. They proved themselves useful in countless cases. So in general you do good by just following them. There are however cases where it might be worth violating them, but you have to have some very good reasons and you should be aware of the consequences.
Ultimately, it's your code, your design, your decision. Maybe you guess wrong, but some lessons have to be learned the hard way. Next time you know what to do and, more important, why. Making your own experiences is always valuable.
You should stick to the delegate design. You never know when you might need help with the code and people expect to use a delegate. This would spaghetti-fy your code in my opinion.
Remember that Views get recycled, especially in tableviews. Once the view is out of sight, it is re-used, so any logic you put in there would be complicated to maintain to say the least
Trausti Thor is right. As soon as you begin that kind of short cut, it's the death of a thousand compromises (or to put it another way, the technical debt just heaps up until it the resulting code base is so scary no one wants to touch it in case they break something else).
Whenever you have the chance to do it right, first time, do it, because there will be times when commercial, or other, pressures force you to do otherwise and these are unavoidable but you want to minimise the impact of such compromises by making them the exception.
Finally, if it's an exception, almost a blot on your code, you are probably going to be more inclined to go back and fix it during quieter times.

When declaration of property is unavoidable -- Objective C 2.0

Working on a maintenance project, I am struggling with lot of messy code. In the current assignment, I found that the previous developer has defined property (and synthesize) for each and every iVar and IBOutlet of the class.
As per my understanding, I was used to declare properly of only those variable, which I intended to use outside of that class. And most of the time, I need not to declare property (and synthesize, of course) for any of the IBOutlet.
Can I have any Answer or Document on "When to declaring property and synthesize is needed (or essential)" ?
EDIT: After reading the Post which Dr.Kameleon Pointed, another Question comes to my mind: What loopholes can be there in code, If I declare each and every iVar as a Propery and Synthesize them? Can I go that way?
I think in general it's hard to argue that having an extra property or two is all that bad. That being said, including lots and lots of properties and variables can clutter things up and make the code difficult to understand and maintain. And you don't really need an IBOutlet for every frazmabob in your view. So if you're looking to trim the fat a bit, just get rid of anything you don't need to manipulate at runtime. It sounds simple because it is - the only reason to include a variable/property is if you anticipate using it at runtime.
As for presenting properties to the outside world, you're right, it is a primary concept of OO programming to hide things when they don't need to be presented. This is very important if you are part of a team and you don't want others mucking with your data. So go for it - clean up that code and make life easier for yourself and others down the road.
There is no as such rule about when to use property and when to use ivar. Using both have their own advantage-
Using ivar-
using ivar provide small performance benefit.
User has to do memory management manually by reference counting
Using Property-
this ensures KVO compliance code.
By using property, memory management is taken by Accessors.
You can checkout following topic for more insight information - http://cocoawithlove.com/2010/03/dynamic-ivars-solving-fragile-base.html
In my opinion, i always prefer to use property as it has lot of benefit over ivars.

Is it right having ViewControllers with a lots of code?

I'm still quite new to Cocoa and Objective-C (<1 year). My App now has some 50+ classes, but some of the ViewControllers get quite crowded with code, like 700 lines or more.
My question is: is it fine to have a "large" ViewController or are there patterns for splitting up code into fractions? A lots of the code is implementing delegate methods, thats why I don't have an idea how to move it away.
I know, I can structurize with pragma marks though.
Thanks for any input.
EDIT (Dec 2013): there is a great article from Chris Eidhof of objc.io regarding this subject. He also talked about that subject on Macoun 2013/Frankfurt. Separating out the UITableView protocols are a great pattern.
EDIT2 There are also 2 videos on NSScreencast explaining concepts of refactoring ViewController (episode #102 and #103).
One of the most common causes of large view controllers that I have seen, is lack of separation b/w Model and Controller in MVC architecture. In other words, are you handling your data in your view controllers?
If yes, rip out the model component from VC and put it into separate class. This will also force your thinking towards a better design.
For reference, In View Controller:
Handling of all changes in the UIView and the UI elements contained within.
All animation, transitions and CALayer operations.
In Model:
All processing of data, including sorting, conversion, storage, etc.
IMHO, 700 lines is not (yet) huge for iOS code, I've seen and handled much worse. Of course, if all your VCs are this big, you have a problem.
You should definitely use and abuse #pragma mark, it's very useful under Xcode at least.
Then if you find you got too much code in one file, you can extract functionality to classes or categories, as better fits.
Creating classes can be very rewarding in the long term to manage recurring tasks in projects (ie connecting to webservice, parsing XML/JSON, interacting with SQLlite, logging, etc...). If you are doing recurrent iOS programming, you can create a 'common' library of useful code that way.
Creating categories, especially on UIViewController can help reducing boilerplate code that takes a lot of place. You can (and probably should) also create a common base UIViewController for your app, that will handle stuff like rotation, maybe logging, navigation, etc... in a centralized part of the code.
You should try to identify what your ViewController is really doing.
If you can separate some concerns you can move them to classes of their own. Find out which properties and ivars are used by the viewControllers methods. If you can find a subset of functions, that use a common subset of ivars/properties, these together are very likely to become a class of their own. The controller would then own such a new class and delegate work to this.
If your ViewController is managing some sort of state, eg. you find the same switch statement or if-chain in 2 or more methods the STATE pattern could make your VC much more readable. But basically you could use any pattern that helps to reduce the VCs responsibilities.
IMHO the ViewController is the place were you would connect the model to the views. Propagating model changes into views and handling user interaction with the views are the only things, that should happen there. All other responsibilities, like calculation, network transfer, parsing, validation... should happen in different classes the VC uses.
You might like the book Clean Code by Robert C. Martin. He explores in depth how code could be structured to increase it's readability and reusability.
You can distribute the code using categories depending on the functionality. Refer http://developer.apple.com/library/mac/#documentation/General/Conceptual/DevPedia-CocoaCore/Category.html
Prefer the use of NSObject class to manage part of your view controller functions. Main reasons code is more clear and easier to debug

How far can you go using subclassing in objective-c?

In an iPhone app, I need to customize the look of a UINavigationController class. For instance, make the bar and font size bigger. My client really needs that, and bigger buttons aswell.
So, instead of writing the class from scratch, I decided to subclass UINavigationController. My question is, can I customize any method or attribute's default value? Is there any restriction while subclassing a class?
It depends what you mean by "restriction". The runtime will not prevent you from subclassing whatever you like, but there are a few gotchas. (Although your answer is specifically about UINavigationController, the title and concept are bigger, so I'll address the bigger issues.)
There may be variables in the parent class which are marked #private and child classes cannot access, versus the default of #protected, which are accessible.
Some classes are designed for subclassing (and most AppKit and UIKit classes are) but for others it is extremely unwise. For example, key foundation classes like NSString, NSMutableArray, etc. are actually class clusters, meaning an instance of the class may actually be one of several private classes.
Classes that are designed for subclassing will usually document the key methods which must be overridden. For example, NSDictionary and NSMutableDictionary describe a few "primitive" methods which every other method calls down to, so overriding 2 or 3 in each case is sufficient to change the behavior without re-implementing everything else.
Be extremely careful to call the parent class' implementation of your overridden method if and when it is necessary. This can be especially important in UI classes, which often have more complex behavior than simple get/set data classes.
In this case, you're exactly right to not write the class from scratch — that would be a Bad Idea™. If you want to change the default value of an attribute (field?), you can set the desired value in an initializer after calling the parent's initializer. However, if you do this, make sure you're not hosing something in the parent class, and always test thoroughly.
Apple has reserved methods that start with "_" for their own use, so I'd echo Marc's caution to not touch those at all. Everything else is fair game, within reason of course. :-)
No, feel free to go nuts. Many Cocoa classes are not as subclassing-friendly as others (especially those that are meant to rely more on delegate control) and may not expose the functionality you need, but you can feel free to subclass any method that's not private (begins with a _ prefix). You could even subclass those if you really wanted to, although on the iPhone chances are Apple would reject your app.

iPhone SDK: speed vs mem footprint

In my app delegate I have a variable which various controllers use (thank to the news group advise on how to access such variable from controllers). Each controller may need to access it more then once. I use this code:
((MyAppDelegate *) [UIApplication sharedApplication].delegate).soundEffects
Ignoring readably issue (as noneone other them me will ever see these src) would it change anything if in the controller init I have I get a pointer to the app delegate object and just access it like so:
...
MyAppDelegate *foo = [UIApplication sharedApplication].delegate
...
foo.soundEffects ...
It looks like second approach would require more mem storage to hold instance variable foo, while my first approach could be slower to get to the variable.
What is better?
thanks
You don't need to worry about speed or memory in this case. Resist the temptation to optimize before you know you have a problem. You're much better served by focusing on the readability of your code, even if you're the only one reading it. Well designed code that's easier to read and maintain will have fewer bugs, and will be easier to optimize if you do find yourself facing speed or memory problems down the road. Don't hesitate to sacrifice a few bytes here and there if it makes your code easier to read.
In this case, your proposed change is certainly a step in the right direction, so go ahead and make this incremental change if you'd like.
If you're feeling bold and want to take another step in the right direction, you could add a soundEffects member variable to each controller that needs it, make it a property using #property (nonatomic, retain), and set that property after you construct each controller (in your app delegate's application:didFinishLaunchingWithOptions:, and wherever else you might be constructing these controllers). This way your controllers don't even need to know that the app delegate exists. This "loose coupling" is an object oriented design virtue that minimizes the dependencies between your objects, making them easier to maintain.