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.
Related
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.
I have a view that is to be shown from different screens in my app. I dont want to allocate and initialize the view from each screen. I thought this could be done using two approaches:
1) Initialize the view in App Delegate and access the same from all the screens. (Note: I dont want add the view on window because my app only supports landscape orientation and this will result in lot of spaghetti code to manage the view orientation.)
2) Make the view singleton instead
Now, there has been a lot debate on whether the Singleton pattern in general is good or bad. Also, I know that using singletons for view controllers is considered as bad idea .
Is there any better approach to achieve this??
Using singletons is not a bad idea, it's actually a solid pattern that allows storage of fast accessible data throughout the application lifecycle. NSUserDefaults, NSFileManager, NSNotificationCenter and many other Apple default classes use singleton pattern. If your view takes up too much memory (e.g. it has a lot of heavy graphical assets on it), then you should have a class that creates that view each time you call it and loads it into memory for a period of time that the view is used in. If your view is light weight, you should create it statically and keep it alive throughout the entire App's lifecycle using singleton class.
Using a singleton or using a property of your app delegate are equivalent ways of accomplishing the same thing. One can also use a common structure passed to all of the "interested parties".
Which you choose is up to you -- the "ideal" choice depends on the circumstances.
Do be wary, however, of ending up with dozens or hundreds of singletons -- this usually indicates that your design is not very well thought out.
Singletons are modern global variables so I try to avoid them unless absolutely necessary. The use of Apple's low memory globals caused all sorts of problems when porting to Carbon.
If you are maintaining libraries beware that there will be an instance of the singleton for each library so you need to be careful who is accessing them. I ran into this with the Loki singleton implementation (C++), although it would make sense that an Objective-C singleton would have the same issue.
I have a view that is to be shown from different screens in my app. I
dont want to allocate and initialize the view from each screen.
Why don't you want to create the view as you need it? Views use a lot of memory:
a half-screen view (240*320) on a non-retina iPhone requires 300KB just for the pixels.
the same view on a retina display requires 1.2MB
For that reason alone, allocating your common view only when you actually need it seems like a very good idea. There's nothing to be gained by hanging onto the view when it's not being displayed.
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.
I'm building an application that reads rss files something like Bing or Pulse, so I've built a class (UIViewController) that shows each individual entry in the feed and a class that contains that list of entries and another class that shows all the feeds at once, and I've not used any xib files so I've implemented a method in each class that gets called after each rotation to reset the frames of the views inside that class. But I'm facing a problem in the memory especially when calling that method when a rotation happens knowing that it just assigns a CGRect to each frame in the view.
So could you please help me to avoid this problem or suggest a different way to avoid it, and am I right about not using xib files or should I use them when ever I can and set the rotation thing inside them (using the auto resizing mask).
And if there is some complex free example like those applications, could any body point me to it.
Any help would be greatly appreciated,
and thanks in advance...
First, there is no reason to avoid nib files when they are useful to you. They are often useful. There is no reason to use nib files when they are not useful to you. If you have complex layout, they are definitely very useful. Whether to use them or not, however, is a personal choice based on the particular application. As a beginner, I would recommend using them and getting comfortable with them, and particularly relying on the Xcode templates to set them up correctly.
Nib files aren't your issue, one way or another here. You're leaking memory, and you need to investigate why. First, run the static analyzer to make sure there are no obvious errors. Then run your app under Instruments (Leaks) and look for large leaks. Then run your app under Instruments (Allocations) and look for what's eating the most memory. That should point you to your error.
The most likely cause, without any insight into your code, is that you are misusing ivars. Make sure that you access your ivars through accessors (except in init, dealloc and in the accessors). Directly accessing your ivars is the #1 cause of memory problems in iOS.
Release the objects properly which has been allocated and defined globally. Do not release the object of your UIViewController when it is active. Most of the leakage problems occur by releasing the object of the UIViewController before it reaches out of scope.
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.