Significance/Need of setting the properties to nil in viewDidUnload - iphone

What is the significance of setting the properties to nil in viewDidUnload in both the aspects i.e. with ARC or without ARC?
Does it only matter in case of IBOulets? Don't we need to set the other properties (that are not IBOulets) to nil?
What can be the consequences if I don't do that? I haven't set them nil before and haven't observe any consequences.
Help is really appreciated.

Setting IBOutlets to nil in viewDidUnload tells the compiler to release the outlets on memory warning.because on memory warning ..viewDidUnload and didReceiveMemoryWarning of the viewcontrollers gets called..Normally in ViewDidUnload the IBOutlets are set to nil and in didReceiveMemoryWarning properties or objects are released.Hence in such a case memory is regained and thus your app can continue to function else continuous pooling causes in crash due to low memory

After reading a lot articles on the web and going through similar questions on stackoverflow.com I reached at the following understanding:
viewDidUnload is called by the compiler in low memory situation.
We should set those properties to nil in the method, which are being re-instanciated in viewDidLoad. Almost all IBOutlet components falls under the category. So better we declare the IBOutlets to nil in the method. Not doing so will lead to continuous pooling and may cause crash due to low memory in future(the time, the app continues to run).
I also read that we should not nil the instances of the class like NSString(may cause crash), which is right as per my experience. But reason for that I don't know.
It has nothing to deal with ARC. Setting a property to nil simply means that the property doesnot keep the refrence of any memory location anymore.
I will keep on updating this answer every time i came to know something more about it.
Thanks.

Related

Setting UIWebView delegate property to nil

According to documentation, UIWebView delegate property needs to be set to nil before disposing of the UIWebView instance.
My question is : If the UIWebView is setup in IB with its delegate points to the file owner which is a viewController. And the UIWebView and its superview is never disposed of during the course of execution, does the delegate need to be set to nil ?
Am asking this because it seems difficult to get a reference to UIWebView.
Hope somebody knowledgeable could give some hints.
(non-arc setup)
It is always good practice to follow the suggestions in the documentation. In most cases, what you're suggesting is generally correct: there isn't really a need to set the delegate to nil as the only time the object will be destroyed is when execution ends. However, that is similar to saying "I don't need to free this heap space because it will only be freed immediately before main returns"...
A more pressing problem is what happens if the application receives a low memory warning. If a memory warning is received and the UIWebView is unloaded and the delegate is NOT set to nil, then you may end up with a memory leak behind the scenes depending on what UIWebView does when it sets up/removes its delegate.
If you set the delegate to nil on destruction, then whatever needs to happen is handled by UIWebView when it detects its delegate is set to nil. If you don't, and the instance is unpredictably destroyed (say, due to a low memory warning), then once the warning has cleared, the loading will take place again and whatever procedure is taken to set a UIWebView's delegate will be run twice, without the 'shut down' procedure ever happening in between. Given their insistence that you set the delegate to nil on destruction, I imagine this manifests itself as a memory leak or something similarly sinister.

ARC and Interface Builder

I have an interesting question about interface builder and ARC. I am building a view controller that will be initialized with a xib. I use the tap-and-drag capability of interface builder to create necessary property outlets for my xib. This initalizes the property as (weak, nonatomic). Sounds fine to me.
What's throwing me off is that lines such as [self setCategoryButton:nil]; are automatically added to viewDidUnload. I understand and used this before ARC. However, since these are weak references, wouldn't they automatically be cleared when the view unloads?
I suppose I could see the value in nil-ing these properties if those views are retained by other objects, but that seems an unusual case to me... Just wanted to get further feedback on the point.
Thanks,
Kurt
I filed a bug on this a while back, and the response that I got was that this is intentional behavior. Since Xcode cannot verify that there are no other strong references to the view, it cannot actually guarantee that the weak pointer would be automatically cleared in -viewDidUnload. Thus, they clear it for you.
Personally, I think this is a lame reason, but that's the reason that was given.
It will only be set to nil in iOS5 or later (iOS 4 does not automatically nil weak pointers), so it is there for safety in the auto generated code. I've been wondering about this myself and that's the only reason I can come up with.
From Documentation, the viewDidUnload
"This method ...is your chance to perform any final cleanup. ... "
"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"
From Documentation, about weak (Setter Semantics)
Specifies that there is a weak (non-owning) relationship to the destination object.
If the destination object is deallocated,the property value is automatically set to nil.
So it's obvious. It's consistant on the rules.Is not about the object that your property points,but just nullify your property based on the above rule of weak.
The viewDidUnload suppose that's your weak property can't be point to any object,
because that object is deallocated (based on the place of viewDidUnload in the life cycle of a View Controller). And simply cleans it with the nil.
It's safe for you, explicit to the weak rule and memory efficient.
The compiler can't be sure that you took the care about the pointed object.
He just need to ensure the clean up.
Since the property is weak, the reference in your object won't affect the retain count of the object. So yes, there's no point in setting the object as nil. At least that's how I understand it.

Managing memory warnings in IOS. Any pointers?

in my app, sometimes I get a level 1 memory warning which I think is acceptable given the amount of work it is doing. When that happens, it calls the viewdidunload for one of the views which is part of the tabbarviewcontroller. In the viewdidunload, i set the outlets to nil which I think is totally normal.
The issue arises if I try to access that class again. Since it was deallocated, it will throw a bad access error which prevents me from showing that view again. If I don't set those outlets to nil then it won't crash which is normal but the convention is always to set any outlets to nul in the viewdidunload.
Any pointers for handling memory warnings in this case? I don't want to delete the code i have in the viewdidunload method since it is going against the convention.
I forgot to add that i subclassed the tabbarcontroller >_<
In that case, again the subviews added to xib file will be allocated when you load that view again. And if you want to customize something, do that in viewDidLoad method.
Where do the views which were deallocate get allocated? It sounds like you are deallocating a view in viewDidUnload that was not allocate in, for example, viewDidLoad. Instead it might have been created somewhere else, so it does not get recreated then the viewController's view is reloaded.

Querying to an instance if it is already deallocated

I know about memory management rules and there is no need of what I am asking if I follow these rules. But, I wonder if there is a way to know if an instance is already deallocated without throwing an exception.
My app uses an object what any view on my app can become its delegate. Sometimes, I'm getting this well known error. I can avoid this by setting the delegate to nil on the dealloc method of the current delegate owner.
In summary... Do I have any way to know if an object is deallocated?
Thanks.
Can I tell if a pointer now points to garbage?
No, not really. Once an object is deallocated, its memory can be reused at any time. Sometimes it'll actually point to garbage (causing a crash), sometimes it'll point to a different Obj-C object, and sometimes the memory will not have been reused yet.
The main exception is that if you set the environment variable NSZombieEnabled=YES (in "edit scheme" somewhere in Xcode 4), the memory used by objects will never be deallocated (unless you also set NSDeallocateZombies=YES, or so); instead, sending a message to the zombie will cause an exception. It's useful for debugging, largely because it tells you the class name of the instance that got deallocated.
I usually try to set pointers to nil once the underlying object is deallocated. In this case, you can simply check whether the pointer is nil to see if the object has been deallocated. This isn't always possible, but often is.
The answer to your question is unequivocally "no". You can't ask a pointer whether it is valid without risking a crash due to invalid pointer access. The good news is that setting delegate objects to nil is the correct thing to do, so what you're currently doing is good.

How to properly compose a "viewDidLoad" method

I'm not entirely new to iPhone dev, but I ran across a situation where I was unsure about the best design choice for my code.
I have a view controller which asynchronously fetches an image from the internet and loads it into an image view. When the app receives a memory warning however, the imageView is released by didReceiveMemoryWarning. If the app receives a memory warning while loading an image, the imageView is nil by the time my code tries to load the image into the imageView.
What is the best practice for viewDidLoad? Should I just instantiate any variables that I may need later on? Or should I just check for nil values elsewhere in my code?
Also, in viewDidUnload, should I just set IBOutlet variables to nil? Why is this?
Thanks! -Matt
Why not just create the image view on demand when the image is loaded? No need to create it any earlier. Or, if you do, then just have code to recreate it if it has been released.
In viewdidunload you should release resources that you created in viewdidload (or load view). Including any IBoutlets that interface builder hooked up for you. It's good practice to set these variables to nil to ensure they won't be inadvertently accessed after release, or double released.
IBOutlets can be both instance variables and properties. In both case, we should release the references when the view, which is top most superview, is unloaded. Setting the IBOutlet retained properties to nil releases the reference automatically, but for instance variables we need to release them. We still need to set instance variables to nil because viewDidUnload is not dealloc, so we must comply with the managed memory rule or we might have invalid references sitting around inside the instance.
I don't think there are rules about what you should do in viewDidLoad, but if you did release and set some variables to nil in viewDidUnload, you need not have to check for nil again in the viewDidLoad unless you don't trust the framework.