When is viewDidLoad called? - iphone

Is it safe to assume that an attribute, namely fetchedResultsController, of chatViewController, an instance of a subclass of UITableViewController, is always nil when viewDidLoad is called, assuming that it's set to nil in viewDidUnload? Phew!
If that's the case, then I see no immediate need to redefine the accessor function like in the Xcode example application CoreDataBooks. I'd rather just put all that code in viewDidLoad instead of in a separate function because that's the only place I'll use it.

viewDidLoad is called after your view is loaded. Whether or not fetchedResultsController is nil or not depends on how the viewController is initialized. For example, when creating the detailViewController, you could set its fetchedViewController before viewDidLoad is called:
RecipeDetailViewController *detailViewController = [[RecipeDetailViewController alloc] initWithStyle:UITableViewStyleGrouped];
detailViewController.fetchedResultsController = fetchedResultsController;
[self.navigationController pushViewController:detailViewController animated:animated];
[detailViewController release];
That said, then nil'ing fetchedResultsController in viewDidUnload would ensure that it's nil.

ViewDidLoad Called in These Secnarion:-
1.when we push the view controller after creating it’s object by segue or by stoary board id.
2.it called more than one in the case of creating instance more time in application and push it again and again.for example:-if you implement like coaursal(that having required to additional controller during scrolling) like that it’s need so it can called multiple times viewDidLoad.
3.it called when all memory instance (uiviewcontroller and it’s subclass instantiated) that means when our view is ready to load in memory with the address.
4.Remember only child class controller object is created..parent class object never been instantiated during normal Secnarion.

You have to assume that viewDidLoad can be called multiple times. If there is a memory warning sent, your view controller will unload the view from memory, and the next time it is needed viewDidLoad will be called.

viewDidLoad is called only when view is instantiated for first time . If you're not recreating the view controller each time in your application, you'll only get it called once (and called again if you get a memory warning, and the view is nil'd out).

Related

poptorootviewcontroller not calling dealloc methods and viewdidappear method of rootview controller in a sequence

I have a navigation controller with 4 VCs pushed into it. I have a singleton class with a delegate property that is set to the VC which is on top of the stack. I am setting this delegate to nil in the dealloc method of each VC. I am setting the delegate in the viewdidappear method of the rootVC.
When I pop back to root VC from the 4th VC, the sequence of calling the dealloc methods (of all the VCs in stack) and viewdidappear method is following:
"FirstVC dealloc called"
"SecondVC dealloc called"
"viewdidappear of root VC is called"
"ThirdVC dealloc called"
Now, the issue I am facing is that the delegate gets set to nil even though I am setting it to self in the root VC's viewdidappear method (which is visible from the control flow too). How can I prevent this situation? I want the viewdidappear method to get called once all the VCs are really deallocated.
Thanks,
Obaid
Since you can't predict the order of method calls unless Apple publishes some guarantee of what they are, perhaps you could program the singleton to be defensive by creating a method such as:
- (void)removeDelegate:(UIViewController *)oldDelegate;
If the delegate matches the specified old delegate, set it to nil.
dealloc is called automatically once a object is no longer needed. When you pop the ThirdVC, since the delegate property is still retaining it, dealloc doesn't get called. Then, when your rootVC's viewDidAppear gets called, it sets the rootVC as the delegate. At this momment, your thirdVC is no longer needed, which triggers the dealloc.
One thing you could do is set the delegate property to nil not on dealloc, but on the viewWillDisappear method of each ViewController, since this method will surely get called before the next ViewController appears.

On iOS, if a view controller has no view yet, why does NSLog(#"self.view is %p", self.view) crash?

If a new iOS project is created with an Empty App template in Xcode 4.3.2, and in AppDelegate.m:
self.window.rootViewController = [[FooViewController alloc] init];
and in FooViewController's viewDidLoad, the following:
NSLog(#"self.view is %p", self.view);
NSLog(#"self.view is %#", self.view);
will print out the view, so it looks like the default loadView will instantiate a view and assign it to self.view.
So if I override loadView with an all empty method, and comment out the second NSLog statement above, I expect the first NSLog statement to print out 0x0, but instead the app crashed due to bad memory access right at that NSLog line. Why would that be?
Okay, after a knee-jerk and obviously wrong answer, I tried this. The Empty App template would not have a rootViewController, so I used a single screen template. After running, I see that you are getting a stack overflow. In trying to access self.view, you are calling the view property on the superclass, which is then trying to load the view in order to return it, which is calling viewDidLoad, etc., as far as I can see. The other NSLog statement does the same.
The documentation for the view property in UIViewController states:
Because accessing this property can cause the view to be loaded automatically, you can use the isViewLoaded method to determine if the view is currently in memory.
It also has a link to The View Controller Life Cycle, which states:
The steps that occur during the load cycle are as follows:
The load cycle is triggered when the view controller's view property is accessed and the view is not currently in memory.
The view controller calls its loadView method. The default implementation of the loadView method does one of two things:
If the view controller is associated with a storyboard, it loads the views from the storyboard.
If the view controller is not associated with a storyboard, an empty UIView object is created and assigned to the view property.
The view controller calls its viewDidLoad method to allow your subclass to perform any additional load-time tasks.
So when you say:
So if I override loadView with an all empty method
You're deliberately breaking the life cycle, because when your overridden version of loadView finishes, it should have loaded a view. Because it didn't, you get a crash.

i don't know why this table view code crashes

hello i'm studying iOS programming
i created a project, which is an empty application
and i created table view controller without xib file.
and i inserted follow code in didFinishLaunchingWithOptions
TableViewController *tvc = [[TableViewController alloc] init];
[self.window addSubView:tvc.view];
[tvc release];
this code was crashed when i scrolled down. why is that?
when i comment this code
[tvc release];
program doesn't crash.
i didn't write dealloc in AppDelegate file.
why is that??
i think i created table view controller with alloc
so retain count is 1.
and add sub view to window and table view controller retain count is 2.
so i release table view controller
but it crash when i scrolled down.
i don't know why..
help me please
Simple, adding tvc.view as a subview of the window causes tvc.view to be retained but does not retain tvc itself. In essence, your TableViewController instance becomes invalid as soon as you call release on it. The app crashes when you scroll presumably because the TableViewController instance is configured as a delegate or datasource for a UITableView or UIScrollView or any other thing associated with tvc.view.
Also note that the way you are displaying the view is not the recommended way to go about it. Really you should be calling presentModalViewController: or pushViewController: and passing the TableViewController instance. This will cause the TableViewController to be retained until it is dismissed/popped, making it safe for you to call release as in your example code.
Or, since you are doing this setup manually as part of didFinishLaunchingWithOptions, you can also set window.rootViewController directly, though again that's not really recommended. XCode allows you to specify the app's default/root view controller and will automatically set it up for you when the app launches.
Actually you have just added the view alone. So the view alone will be retained. The viewcontroller will be released. But the viewcontroller needs to be the datasource and delegate for the tableview. Since it has been deallocated, that datasource will not have any valid reference and so it crashes.

Invocation of ViewDidLoad after initWithNibName

It appears that ViewDidLoad() is sent to a ViewController only after its View is physically displayed (i.e. via NavigationController pushViewController), and not immediately after initWithNibName(). Is this a behavior I can rely on? I would like to get the chance to set the member variables of my view so that all the members are valid by the time ViewDidLoad() is invoked.
You can set up member variables and other such things in initWithNibName:bundle:.
- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle {
if (self = [super initWithNibName:nibName bundle:nibBundle]) {
// set up ivars and other stuff here.
someIvar = someValue;
}
return self;
}
You are correct that viewDidLoad: is only sent when the view is physically displayed, i.e when it is added to some visible view (which may sometimes be never if the user does not reach that view). So it's useful to split the functionality and think about what you can do at init time and what happens at view load time.
As Marcelo Cantos notes in the comment, viewDidLoad: is generally a fine place to do all sorts of setup work, using the concept of "lazy loading," so that you defer the setup until as late time as possible.
viewDidLoad is called before a view controller is displayed for the first time, not immediately after initWithNibName. For example, if you have a tab bar controller, all of the child view controllers will be initd at launch, but viewDidLoad will only be called when you click on the appropriate tab the first time. It's generally a good idea to initialize memory-intensive items in viewDidLoad, so as to avoid using unnecessary memory.
I found that if I override initiWithNibName in the view controller, the viewDidLoad method is not called. I have to call it manually [self viewDidLoad]. But if I do not override initWithNibName: viewDidLoad is called. I am working with 4 view controllers in tab bar controller. the tab bar controller is loaded from another view.
Sorry to unearth an old thread, but this solved it for me...
-(void)viewDidLoad is only called after -(void)loadView has done its thing. In the docs for loadView:
The view controller calls this method when its view property is requested but is currently nil.
My view controller only has viewDidLoad called after its view is request by a UITabBarItem, meaning viewDidLoad is only called in the viewController once the tab bar button is pressed. I, like the OP, want viewDidLoad to be called directly after the nib is loaded, so it's contents (titles, etc) can be populated before the user clicks the tab button.
So, after calling "self = [super initWithNibName:#"nibName" bundle:nil];" in the view controller's custom initialiser, I immediately called '[self view]' afterwards. As the view is requested earlier than when it is requested by the UITabBarItem (which calls 'addSubview'), the view is initialised fully during initialisation, rather than when requested.
Hope this helps.

Why is viewDidUnload called less often than viewDidLoad?

I put NSLog(#"%#::%#", [[self class] description], NSStringFromSelector(_cmd)); in both viewDidLoad and viewDidUnload of a view controller.
In the log, I found viewDidLoad is called a lot more than viewDidUnload when the app moves to and from different .nibs.
Why?
The viewDidLoad and viewDidUnload is not corresponding to each other.
The viewDidUnload will only be called when you receive a memory warning. The system then will automatically call your viewDidUnload.
In the normal case, when you push a MyViewController and pop it out. The life cycle will happens like this:
init
viewDidLoad
release
That means, whenever you init and push/present a view, a viewDidLoad will be called. But when you pop the view, the release will be called in normal case and viewDidUnload will be called in memory warning case.
This is quite implicit and Apple doesn't state it clearly on the Guide. Here is some reference: Load and Unload cycle
I imagine that in the cases where -viewDidUnload wasn't called, the view controller was released.
viewDidLoad: controller loads view
viewDidUnload: memory warning, controller unloads view
viewDidLoad: controller loads view again
-: controller gets released, doesn't explicitly unload the view
You and up with 2 -viewDidLoad calls and 1 `-viewDidUnload' call.
Maybe also put a NSLog into the -dealloc method and see if the number of -dealloc and -viewDidUnload calls combined matches the number of -viewDidLoad calls.
when a new view loads, the old view can still be loaded in the background.
you are searching for viewWillAppear as conterpart i think.
views only unload in case of a memorywarning.