In the template Apple gives you, I see that they have:
/*
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}
*/
I understand that you want your super class to do any loading of the view before your own view. For viewDidDisappear, do you do the same thing for the same reason?
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
}
Yes always call the super class method first to have it complete so then you can override any behaviour subsequently in your inherited classes method.
The only exception to this is the dealloc method where you should call [super dealloc] last to make sure you've cleared up your own class properly before any references might get lost and cause a memory leak.
I would say that things should always be taken apart in the opposite order they are built up. You call [super viewWillAppear:animated] at the beginning of viewWillAppear so the super class has a chance to set up the default actions, then you get your opportunity to modify.
For the call to [super viewDidDisappear:animated] you should do your disappearing code before calling the super one at the end of your viewDidDisappear. That way if you have any references to the default view contents they are not released before you are done with them. If you don't use anything in the super class then it is probably irrelevant.
Related
Does anyone have an official reference for why methods such as 'viewWillDisappear' should not be called directly? There are several existing posts on the subject but no official link, only opinions.
It does not make sense to do so as it is calling a method "out of cycle" from the lifetime management of a view. They can be, and in many cases are, overridden of course.
https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/RespondingtoDisplay-Notifications/RespondingtoDisplay-Notifications.html
The issue in question is for some code I encountered where 'viewWillDisappear' is being called from some method. It is really the content of the 'viewWillDisappear' method that is needed to be called.
Example:
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
// The following two methods are the ones that need to be called below
[self someMethod];
[self anotherMethod];
}
- (void)delegateMethod
{
[self viewWillDisappear:YES];
// Do some other work
// View is moved off-screen, not deallocated, and therefore, does not "disappear"
}
Instinctively it appears wrong to call any of the view hierarchy methods directly (e.g. viewWillAppear, viewDidAppear, viewWillDisappear, viewDidDisappear). If you tell 'self' and the 'super' view that viewWillDisappear it may do something in the framework that could cause problems later on. I think these methods should be called by the framework only. However, this is my opinion and not an official source. The header files don't seem to provide anything about this.
Any help appreciated.
There is no technical reason you can't.
But you shouldn't.
It's bad coding practice and you might confuse the reader or, worse, make him/her not trust you.
Good coding practice would be the following:
- (void)delegateMethod
{
[self doCommonWork];
}
- (void)viewWillDisappear:(BOOL)animated
{
[self doCommonWork];
}
- (void)doCommonWork
{
// …
}
I am refactoring some Objective-C code someone wrote for iOS more than 3 years ago.
I see the viewDidDisapppear: method was overridden this way:
- (void)viewDidDisappear:(BOOL)animated
{
[pagingView unloadData];
[super viewDidDisappear:animated];
}
It works fine, however I am wondering, the line:
[super viewDidDisappear:animated];
should be at the end or at the beginning.
I know for viewDidAppear: it is good practice to write:
[super viewDidAppear:animated];
as the first line.
Also, I know for dealloc (if we not using ARC), we write:
[super dealloc];
at the end.
So I am a bit confused in the case of viewDidDisapppear:, where it should be.
It makes sense for me to invoke the super class' method at the end, but I am kind of confused, not sure if it is good practice or not.
Please let me know if you know the exact answer.
Thanks in advance!!!
Basically you want to tear down everything before you call the super view's "viewDidDisappear", otherwise stuff might get released (or set to nil or whatever) unexpectedly out from under you.
Also, you do not call [super dealloc] in the case of ARC.
Is the viewDidUnload & didReceiveMemoryWarning optional if no extra logic is added to these 2 functions (i.e. save to remove the following codes)?
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload {
[super viewDidUnload];
}
Yes, if no extra logic is added to these 2 functions.
But you need to inspect carefully the whether any logic is necessary?
You also need to understand when these function is run in this document by Apple
The View Controller Life Cycle
Then you decide whether you need any extra logic.
Yes.
According to the documentation, the default implementation of didReceiveMemoryWarning "attempts to release the view controller’s view". So if you don't need anything else to happen, then you can delete the code and rely on the default.
When providing an implementation of viewWillAppear, viewDidLoad, viewDidAppear, loadView etc.
Should the calls to the superclasses corresponding methods be made before or after performing custom action?
What are some possible consequences if performed in the wrong order?
i.e.
should it be:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
stuff
}
or
- (void)viewWillAppear:(BOOL)animated
{
stuff
[super viewWillAppear:animated];
}
etc.
For the vast majority of things you'd like to do, it won't make any difference at all. It's convenient to place the call to "super" first, because then it's easy to check later an make sure you are calling super. Apple's documentation just states that "you must call super at some point in your implementation".
There is one case where it is more likely to matter. If you are not inheriting directly from UIViewController, but instead from another custom class, then you should research the specific behavior of that class in making your decision. In general, calling super first makes for a good design pattern to make it easy to always predict behavior when debugging.
Does it matter if I call the method of the super class first thing or at the end? For example
-(void)didReceiveMemoryWarning {
/* do a bunch of stuff */
[super didReceiveMemoryWarning];
}
versus
-(void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
/* do a bunch of stuff */
}
same question for other methods like viewWillAppear, willRotateToInterfaceOrientation etc.
I am looking for meaningful differences, not just stylistic, or philosophical (although those are welcome too).
Typical Cocoa convention:
If you are performing setup, call
super FIRST
If you are performing
teardown, call super LAST
So, initialization, viewDidLoad, etc.. fall under the first case. Memory warnings, viewDidUnload, and dealloc fall under the second case.
You should also design your classes to follow this convention. Any deviations should be specifically noted.
Related SO answer:
`[super viewDidLoad]` convention
To add:
The rationale for calling super first during setup, is that you want to make sure everything is in place before you extend functionality. The corollary, is that when you are deallocating, you don't want any superclass ivars your subclass depends on to be dealloced before you have a chance to handle them.
This makes sense in reference to UI updates as well as noted in the comments below.
It depends on functionality, you either want to do something after the super class did its thing or before.
For example if superclass holds some UI elements and you extend it and your class will hold some more UI elements. To get the size to fit your whole object you would probably call super class to calculate the size of its elements and then you add to that size the size of the elements that you added.
It would not make sense otherwise - super class is not aware of your elements so it would overwritten your calculation. Again, this depends on implementation.
There's a specific case where you need to call super method as last thing:
-(void)dealloc
{
...
[super dealloc];
}