Releasing a UIViewController as a property - objective-c

I am having an interesting memory management problem with an iOS app.
I have a property which when release using [self.propertyName release]; will cause the property to be released twice and cause a bad memory access exception on an iPad 1/iOS 4 device (in the dealloc of the property).
When the this code is changed to [_propertyName release]; (accessing the local variable instead of the property), this will cause a leak on an iPad 3/iOS 5.
Of course, I can stop this from happening by checking the OS version, but I would like to understand what I am doing wrong.
Some more details:
The property is a subclass of UIViewController, as is the object who owns the property. I am adding the property's UIView as a subview. I have heard this is not good practice, but we are doing it elsewhere without the memory problems.
The test cases are:
iPad 1, iOS 4.2 - Needs to release using the ivar [_propertyName release]
iPad 2, iOS 5.0 - Needs to release using the property [self.propertyName release]
iPad 3, iOS 5.1 - Needs to release using the property [self.propertyName release]

Adding another viewController's view as a subview is bound to cause strange issues, when you release the other viewController it's view will still be retained by your main view but it's viewController will have disappeared.
That said self.propertyName = nil is the best way to release properties, just make sure you have removed the subview from your main view first.

Related

Managing View outlets in ios 5.0 and ios 6.0

I am working on an iPad application which is converted to ARC. Application is for os >= ios 5.0. So my doubt is that, how do I manage viewOutlets? I use -(void)didReceivememoryWarning to set ViewOutlets to nil. But in ios 5.0 and 5.1 application shows lots of memory leaks. As -(void)viewDidUnload is deprecated in ios 6.0 , I am not using the same in the application. Is the correct way to manage outlets? Please give me a quick reply.
ARC (automatic reference counting) features is available in iOS 5 and ahead (iOS 6 and so on..) version.
When you are using ARC unable in your project, you dont need to `manually release any object` that you have allocated for your stuff.
ARC will automatic handle this one.so it will beneficial for `Memory Management`.
Hope ,You understand what i m trying to say.
for more clarification , please refer below link:
To ARC or not to ARC? What are the pros and cons?
ARC, worth it or not?
Good Luck !!!
There is NO DIFFERENCE in how you code for iOS 5 vs. iOS 6.
If you are having problems, it's because you don't understand what viewDidUnload does and when it's called.
viewDidUnload is called when the view of the controller is unloaded. In iOS 6, views are never unloaded. In iOS 5 and before, views were almost never unloaded either. So in both cases, pretty much viewDidUnload is never called.
If your program is leaking stuff, it's because you are not releasing things. You always need to release instance variables in dealloc. I suspect that this is your problem.
When the controller's view is unloaded (which only happens in iOS 5 and before, but this is irrelevant), viewDidUnload allows you to optionally discard some resources to save memory, as long as they are resources that will be re-created when the view is loaded again. This usually includes properties and instance variables that are outlets (since when the view is loaded, it will load the Xib again and re-connect the outlets to new objects), as well as any variables that are set in viewDidLoad.
If you coded your program correctly, I can go in there and remove viewDidUnload, and it would not have any effect on the correctness of the program. (Since viewDidUnload is almost never called anyway.)
You should almost never have to use didReceiveMemoryWarning either.

Interface Builder sets control outlets to nil -- why?

Using xcode 4.2 for iPhone app, without ARC ---
When I create an outlet using the interface builder xcode adds two lines of code to my viewController. One in viewDidUnload: -- [self setMyOutlet:nil] and second in dealloc -- [myOutlet release].
I understand the latter (the release). But why set the outlet to nil in viewDidUnload. Doesn't viewDidUnload get called before dealloc and won't setting the outlet to nil negate the release operation in dealloc? Setting to nil makes sense I would think for building a Mac application which is using garbage collection -- but it doesn't make sense for an iPhone app.
Why does the interface builder do this? Should I delete the lines which set the outlets to nil?
viewDidUnload may be called and may be not called. It depends on the current memory usage. dealloc is a place where you should clean all your properties (like arrays, custom objects). In viewDidUnload you clean views and perhaps objects created to support the view. viewDidUnload mean that your view is unloaded (but not whole view controller) and it may be created and loaded again (in viewDidLoad, of course) in the future.
Why to nil - Objective-C Difference between setting nil and
releasing
Understanding How Views Are Loaded and
Unloaded
viewDidUnload is not called everytime before a dealloc, see what the apple docs say..
When a low-memory condition occurs and the current view controller’s
views are not needed, the system may opt to remove those views from
memory. This method is called after the view controller’s view has
been released and is your chance to perform any final cleanup. If your
view controller stores separate references to the view or its
subviews, you should use this method to release those references. You
can also use this method to remove references to any objects that you
created to support the view but that are no longer needed now that the
view is gone. You should not use this method to release user data or
any other information that cannot be easily recreated.
so the idea behind it is too release any unwanted objects which can be created easily.
Now coming to the part where it sets the properties to nil.. it does so because this way you release all the memory and set the objects to nil (thus bringing your down your memory usage) and after this if a dealloc is called your app will not crash as in objective-c you can send release messages to nil objects..
I would advise you to read the apple ViewController Programming Guide , it will clear a lot of your questions.... hoping this clears some of the air.. :D

iOS5 Stable App Crashing in iOS4.3 Simulator

i am getting an NSInvalidArgumentException with reason: -[UITapGestureRecognizer initWithCoder:]: unrecognized selector sent to instance
my understanding was that UITapGestureRecognizers were supported in ios4.x?
is it possible to load a different xib file for sub ios5 versions?
As #mit3z states in his comment on the original question, iOS 4.3 supports this feature only when setup up manually with code. It is not supported with Interface Builder.
Apple would have saved us all grief over this if they simply added this as a build-time warning.
I think you have a NSCoding compliant object that is deallocated before the crash. The UITapGestureRecognizer is allocated at its address and when the disappeared object (but not its reference) tries to call initWithCoder on itself, it actually calls this method on your gestureRecognizer instead.
Then your problem comes from that deallocated object but not from your gestureRecognizer.
Be sure to retain all your IBOutlet properties.

UIView being retained

I'm having real problems tracking down why my UIView isn't deallocing.
I have a UIViewController with several UIViews, all of which are IBOutlet properties that retain.
I'm sure to release the UIView in the dealloc method of the UIViewController. However the dealloc of my UIView is never called. I have no idea what else has retained the UIView.
All the other UIView in my UIViewController dealloc fine, just this one doesn't.
Does anyone have any good techniques for tracking down what could be responsible for this?
Regards,
Rich
I would begin by going into the instruments application and selecting the "leaks" profile. Choose your application and run it to detect leaks.
When it detects your leak, click on the detail indicator by the memory address of the object that has leaked (your UIView). Here you will see your UIView getting allocated, retained, and released and which function call did it.
There is a good WWDC video titled "Session 311 - Advanced Memory Analysis With Instruments" if you want to watch that, they go over it in depth.
Be sure to read Memory Management of Nib Objects from Apple's Memory Management Programming Guide. It describes how to properly declare IBOutlets and when and how to release them in you view controller.
Short version: You should be setting the IBOutlet property to nil in ViewDidUnload.
If that doesn't help, you could try running the Leaks Instruments tool and see if it can find where you're leaking your view.

Using dismissModalViewControllerAnimated won't free any memory

I have a very simple code to show a modal controller (nextController is a class member):
nextController = [[InstructionsScreen alloc] initWithNibName:#"InstructionsScreen" bundle:nil];
[self presentModalViewController:nextController animated:YES];
[nextController release];
And then when the controller should hide:
[self dismissModalViewControllerAnimated:YES];
nextController = nil;
All works good as expected, but when I run instrument Object Allocations it shows that after dismissing the modal controller the memory it allocated is not freed. This becomes a problem because when I show several controllers the memory is over ...
Can anybody give me some clues ? Clang doesn't see any problems, so I'm stuck hitting the memory limit, because the memory of the dismissed controllers won't get released.
EDIT: What I discovered up to now is that it seems to be a leak somewhere in Apple's stuff. Way to reproduce: XCode -> create new project with the template "Utility application". Don't write any code yourself. Just create a new utility application and run it with "Object allocations", choose to see "Created & Still living". Now flip the modal controller few times - you'll see the allocated memory only grows and grows every time the modal controller is appearing and when it's disappearing too ...
There is no leak in the code you show as far as I can see. There could be a leak in InstructionsScreen that would prevent it being deallocated.
I think it's worth running the Static Analyser to see if it finds a leak.
The leak in the Apple template code is interesting. It could be that there is a leak. It seems unlikely but obviously it's not impossible. I would say that it's more likely that it's a false-positive in Instruments, which is why I'd suggest using the Static Analyser.
(You might want to raise a bug report about the leak.)
Modal views are not subviews of the calling view but are instead subview of the apps window and are retained by the window itself. You generally you do not retain a reference to them in the controller that calls them. Instead, evoke the modal view and then have it communicate with the controller by defining the controller as the modal view's delegate.
I think that if you use synthesize to create the accessor for a nextController property defined with retain, then the accessor will retain any object assigned to the property. Simply setting the value to nil will not release the object unless the accessor is set up to do that and I don't think the autogenerated ones do.
You will expressly have to call release before setting to nil.
If this doesn't work, post the code for your definition of the nextController property.