iPhone: Interface Builder leaks memory? - iphone

I have been working on an iPhone project, where we created all the user interface programmatically in code. Now I'm going to start a new iPhone project and thinking of using Interface Builder instead, because it has been recommended to me as being a very useful tool, creating less headache than writing everything in code and in general much faster (regarding development time).
However, my team members have some concerns due to previous problems with using Interface Builder and resulting memory leaks. Therefor they suggest building everything in code again. I don't know where these concerns come from, but maybe someone with more experience than we have can give some insight on that topic.
Doing a simple Google search doesn't really provide any information proofing that there are any problems with memory leaks created by the Interface Builder itself.
By looking at the official documentation from Apple I only see these three things which I have to take care of:
#property (nonatomic, retain) IBOutlet UIUserInterfaceElementClass *anOutlet;
"You should then either synthesize the corresponding accessor methods, or implement them according to the declaration, and (in iPhone OS) release the corresponding variable in dealloc."
- (void)viewDidUnload {
self.anOutlet = nil;
[super viewDidUnload];
}
Anything I missed?

When you assign an IBOutlet via Interface Builder, that object is retained by the controller by default (even without explicitly setting a property with retain). Therefore, you need to either release all outlets, or set a property with assign.
This is a gotcha that gets most people, and leads to the most common of memory leaks. Especially on views that are repeatedly show and removed.

Related

iPhone ARC Release Notes - dealloc on system classes delegates?

I understand the ARC Release Notes, however I have been wondering what does this mean exactly and what are the system classes:
You may implement a dealloc method if you need to manage resources other than releasing instance variables. You do not have to (indeed you cannot) release instance variables, but you may need to invoke [systemClassInstance setDelegate:nil] on system classes and other code that isn’t compiled using ARC.
This is right here ARC Release Notes under the new rules enforced by ARC
What are the so called system classes here?.
I take this to mean any class starting with 'NS' or 'UI'. Apple have not rebuilt all the frameworks from the ground up to use ARC. Instead, your new ARC code should happily interoperate with the existing frameworks if you follow the rules.
In particular, delegate properties of system classes (such as UIApplication) are still declared as (nonatomic, assign) instead of (nonatomic, weak). This means that these properties do not automatically zero themselves when the delegate is deallocated. In fact, assign is a synonym for unsafe_unretained under ARC. Hence the advice to manually nil the delegate property in your dealloc method. This is so that there is no chance that the system class will attempt to access its delegate after it has disappeared.

XCode iPhone automatic property, synthesize and delloc

I have been developing for iPhone from last 1-2 months and all the time for taking IBOutlet I use the following method to declare any property:
In .h files:
#interface ....
{
controlType varName;
}
#property() IBOutlet controlType varName;
In .m files:
at top -#synthesize varName;
in delloc method - [varName release];
Although the method is good but it isn't very good when its taking a couple of minutes just for declaring property.
Is there any automatic process for declaring properties, IBOutlets, IBActions or basic data variables.
I hope there should be some automatic methods for this scenario as this is a very basic process.
Thanks all.
Another one that not many people are aware of is that you can drag from Interface Builder to your header file to create IBActions or IBOutlets.
NOTE: Open the Assistant Editor with focus on the XIB inside IB.
If you create your IBOutlets this way Xcode automatically adds the property, synthesizes it, sets it to nil in viewDidUnload and releases it in dealloc.
You simply drag from the IB object to your header file the same way you would when creating connections between the view objects and their file owners (screenshot below).
In fact, yes!
You no longer need to declare the actual iVar.
In short, simply leave out this part: controlType varName;
For now, you do still need to explicitly "synthesize".
(As far as I can see, they could possibly automate that in the future. But for now you have to "synthesize" to create the setter and getter.)
You do still have to release the memory - there's really no way that could be automated, as memory handling is "real he-man programming."
For any new chums reading, don't forget the "self." part when using the property.
Plus note that XCode4 even has a new automatic thingy. Simply drag from the interface builder, to your .h file, and it will do everything for you -- try it!
In answer to your suplementary question: An IBOutlet DOES NOT PARTICULARLY NEED TO BE a property - you can just use a normal cheap iVar. On the other hand, if you wish, to you can use a property. Furthermore: you can even use the new trick (2011) of not bothering to declare the ivar, just use the property declaration, and shove an IBOutlet in there!
There is an awesome tool that speeds the whole process up: accessorizer.
You write controlType varName; select it and press some buttons and accessorizer will create the property, init, dealloc, viewDidUnload and much more for you. You just have to paste the code into your project.
Try it, a demo is available.
You can save yourself having to release the object by changing the property declaration. If you use:
#property (assign) IBOutlet controlType varName;
retain wont be called on your view so you wont have to release it later. This is generally safe as views are retained when they are added to a parent. If you are removing the views from their parent for some reason then you will have to retain them.
Here's an xcode script to automate the tedium of declaring properties.

good examples of model-view-controller

I'm new to Objective-C and the iPhone and thought I was getting the hang of it until, after many play apps, I ran into a really basic problem around MVCs, NIBs and IB. Are there any really clear explained examples of how to follow this framework that I could go back to?
#interface test1ViewController : UIViewController {
IBOutlet myView *myview;
IBOutlet myModel *mymodel;
}
Both the views and models are linked in by IBOutlets but instantiating the model object either kills the application or produces an object which does not respond to any messages.
I am also unclear as to where to carry best out initialisations. I currently do this over viewDidLoad in the view controller. Is there a standard way to do this and does the simulator actually always start up in the same way? Should one use awakeFromNib? Does it make any difference if I use plain code or the IB? And if I have use the IB, should it include a model object?
The MVC idea would make good sense for me here because I have potentially several views and view controllers all feeding back into - and sharing - one common central data model. Any references or advance on this newbie problem would be more than welcome!
I wouldn't spend too much time worrying about the 'classic' definition of MVC. iOS follows it, but there's a lot of confusing terminology. ("View Controller")
You say trying to use model kills your app. Are you retaining myModel? You have to retain all IBOutlets.
nibs are collections of "Freeze-Dried" objects. When you load a nib, the objects in it are "rehydrated", if you will. This means they spring back to life with all of their properties set to whatever they were when you froze them. So you talk of "instantiating" and "initializing" but this does not apply to IB. The objects are ALREADY instantiated and initialized. Imagine that compiling the nib 'pauses' the objects. When you load the nib, the objects resume doing whatever they were doing when frozen. They will get an awakeFromNib message, so that's a good place to put some code to check on what the state of the app is, see if you have to do stuff with your object to bring it up to speed.
viewDidLoad seems like an "initialization" method but don't be fooled. It's part of the view controller life cycle and it can be called more than once! (If your controller's view is purged as part of a low memory warning, viewDidLoad might be called again if the view has to be... wait for it... reloaded.) So, it's appropriate to put view setup stuff in viewDidLoad, but not other initialization type things.
For the "common data" thing, I like to create a singleton data model class. Your various views can set properties on the model, or send notifications. You can also use KVO (key value observing) to watch for changes in the model.
IB makes functionality invisible. I don't like it and I don't use IB any more, preferring to have everything in code. Then when you look at code you see what is going on - all the navigation controllers, all the formatters etc. - without switching over to IB. Maybe Xcode4 will make it better with integrated IB but I probably won't go back. Lots of people do like IB so try both methods and see what you like best.
IBOutlet/IBAction actually mean nothing to the compiler but they let IB recognise the ivars it can send messages to or that will write to elements in a xib. Your use of it here is a bit simplistic unless you really do have a model that only communicates one way with the xib. What you more usually have is a range of controls in the xib linked to the view object, the view communicating directly with the controller. The controller communicates with the model. Very loosely speaking, model is your internal representation of data and logic, view is what you see, controller is the glue between them.
The MVC line can be fuzzy and you just have to get comfortable with it. If you have a slider control with a value representing some value in your model then it can be hard to think of it as part of the interface especially when you persist the value and use it as a central part of your model. I like the Stanford iPhone class introduction of it. They don't spend a heap of time on it because it can be difficult to follow exactly and there are situations where it isn't best.
Notes from that class - you can find the video on iTunes to follow along.
Your use of viewDidLoad is correct, that's your chance to perform initialization on views and their objects. If using IB you will probably not have much to do there because you can set most properties in the xib. If not using IB you will use it a lot more.
A lot of times something like your model would be wired at runtime by your application delegate or by the view controller itself.
IB is generally used more to link views and controllers together, with the application handing around model(s).
That said, you should be able to have IB create an instance of your model and assign it in an IBOutlet. Was your model OK with just being created without the classic init method being called? Did it implement NSCoding properly?

What's an effective CoreData context/coordinator strategy for this common application pattern?

I have a common application pattern: user enters data in the main view controller, then views it in a table in a modal view controller, where rows can be deleted or modified. I was following the general design strategy from the Stanford iPhone course, but somewhere things went off the rails and all I've been getting is SIGABRT's and exceptions like "Illegal attempt to establish a relationship 'xyz' between objects in different contexts."
As in the Stanford course, I use a singleton class called "Database" which should return the same context whenever requested. So the first commands in my viewDidLoad method on the main view controller are:
dbsingleton = [Database sharedInstance];
nmocontext = [dbsingleton managedObjectContext];
nmocontext is an ivar I use throughout the view controller. When the user wants to see the other view controller, with the table, I alloc-init it, then present it modally. (It has an NSFetchedResultsController that supplies the data from my store.) I've tried various strategies here:
I've made the NSFetchedResultsController a retained property set by the main view controller
I've made the NSManagedObjectContext a retained property set by the main view controller; and
I've used the singleton internally by repeating those two lines of code above at the beginning of the table view controller's viewDidLoad method.
Whichever I go with, the one problem I just can't solve is that after the user closes and deallocs the table view controller (and its NSFetchedResultsController), I start getting crashes in the main view controller when the store is accessed (like the "Illegal attempt" error mentioned above).
What are best practices for dealing with this common application pattern? I am still hoping to make this application iPhone SDK 3.x compatible, but I do seem to have fewer crashes when I'm using iOS 4 -- if there are underlying issues with 3.x that are causing me problems, please let me know and I may target iOS 4 only.
Thank you!
This is just a guess but I assume the following problem for your crashes after closing the tableview:
You declared a property
#property (retain, nonatomic) NSManagedObjectContext* nmocontext;
do you properly release the ivar nmocontext in dealloc?
If yes your problem is the assignment
nmocontext = [dbsingleton managedObjectContext];
This never retains nmocontext within your viewcontroller but you release it on dealloc.
Second:
"Illegal attempt to establish a relationship 'xyz' between objects in different contexts."
This is not a memory management issue, but you probably created another new context to add objects (like in the apple core data iphone samples) and tried to set a NSManagedObject as relationship from a different context.
It sounds like you don't have your singleton properly configured.
A singleton should override release to do nothing such that when it is sent a release message nothing happens. If you do not override release then any random piece of code anywhere in the app can kill the singleton and defeat the entire purpose of using a singleton. The next time you call singleton, you actually get another new object which in this case also returns a new managed object context.
See Cocoa Fundamentals Guide: Creating a Singleton Instance.
Singletons are powerful and flexible but very easy to do wrong. They are so easy to screw up that many experienced developers simply refuse to use them. If don't have experience with them, don't use them when you are just starting out.

Really best practice to retain IBOutlet view elements?

I keep running into situations with UIViewControllers containing a large amount of IBOutlets connecting the controller to its view's subviews (typically UILabels).
Following "best practices", i.e. use retain on all UI elements: #property (retain, nonatomic) UILabel *theElement1, #property (retain, nonatomic) UILabel *theElement2, ... gives me insane amounts of boiler plate code in dealloc and viewDidUnload for the view controller.
The offending IBOutlets are never used nor set outside the UIViewController (the set-method is only used in viewDidUnload and when the nib is loaded) except automatically when the nib is loaded.
The result from "best practice" is:
dealloc littered with [theElement1 release], [theElement2 release] etc.
viewDidUnload with [self setTheElement1:nil], [self setTheElement2:nil] etc.
However, since all of those elements are known to be retained by the view anyway, and the view is released by the UIViewController at appropriate times, I see absolutely no reason whatsoever for me to manually manage this.
The reason for this particular "best practice" (as far as I can tell) is to be consistent with your retains. But once you start having a large amount of outlets, you're more likely to miss handling the some outlet somewhere in either of the two methods, than you'll have trouble correctly changing outlets to "retain" for those special outlets you really want to retain even after the view is goodbye.
Is there some reason for this "best practice" other than the one I know about or should I feel quite free to break this "rule" in the particular case of subviews to an UIViewController's view?
You should stick to this best practice. It protects you from very bizarre crashes when you access IBOutlets after a memory warning. Yes, you need to manually manage your IBOutlets. Accessorizer does a nice job of automating this code.
Before ObjC 2.0, we had to write all of our accessors by hand, too (#property and #synthesize are very new additions to the language). Things have gotten a lot nicer. As we move to the 64-bit ABI and garbage collection, things get even simpler (and you should expect these things eventually to make their way to iPhone).
But for now, follow the memory management rules as laid out in Memory Management of Nib Objects. You trade a really small amount of typing for a huge amount of debugging. (Hmm, looks like they've updated this doc again; time to study up myself.)