The iPad app, I have a TabBarViewController which contain five VC:A,B,C,D,E.
When app launch, every ViewDidLoad called, after that I click the tabBar item, the viewDidLoad won't called again.
I don't know why?
Thanks for help!
If you mean that every viewDidLoad is being called on its own upon application launch, then there must be something you're doing to trigger these events. If however, you mean that each viewDidLoad is only being called the first time you select each tab, then yes this is the intended behavior. Loading each view controller into memory as it's needed.
If you're interested in being notified every time a view controller was selected and therefore about to appear on screen, add the logic to viewWillAppear: instead of viewDidLoad.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// do stuff
}
Related
I was successfully using SideMenu 2.3.4 in my app, then upgraded to v3.1.4. I made the few mods required to adjust to API changes, then ran my app - it crashed after the following UI actions:
Open the menu by tapping on the nav bar button
Tap on item that loads another view (the menu closes, the new view appears)
Tap on the nav bar button to open the menu again
The menu didn't open in response to that last tap before the app crashed. Under the debugger, I saw that after 2, viewDidLoad then viewWillAppear were called for that new view. After 3, viewWillDisappear, viewDidDisappear and viewWillAppear of that same view were called, all without any change in the display.
The crash happened in viewWillAppear because my code counts on viewDidLoad being the first thing that is called after viewDidDisappear. AFAIK, it is legitimate to count on that, since viewDidDisappear is supposed to mean that the view was closed and thus has to be reloaded and viewDidLoad called before any other life-cycle method can be called, i.e., viewWillAppear should not have been called before viewDidLoad.
Am I misunderstanding the iOS view life-cycle? Is this a bug in SideMenu 3.1.4?
Thanks,
Mark
A closer reading of the docs and articles on the net show that I did misunderstand the life-cycle methods.
There is no opposite of viewDidLoad (e.g., viewDidUnload), but in viewDidDisappear one can do this:
if (isBeingDismissed || isMovingFromParentViewController) {
// Do something - viewWillAppear will NOT be called before viewDidLoad.
}
That eliminates the crash I was seeing.
Mark
I've built a large tableview and have found that if I go down a step then click 'back' that the viewdidload function is not called. I need to run a function every time this layer of the UITableView is viewed. Is there a function that will run regardless of whether the view has been previously loaded?
viewDidLoad is called once and only once when the view gets loaded. In your situitation, viewWillAppear might not work as well because it's only called only if the view gets loaded on the canvas. You might need to pass a delegate to the table view controller or view.
You can use :
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
I'm creating a tab bar application for the iPhone and I want whatever view is currently active to be fully unloaded/released if a new tab is selected. When any tab is reselected I want it to have to reload everything. The reason I seek this feature is because all views interact with a single database, and can modify the database. When the views are built they are built off the current database, which means that they can be out of date without a forced reload of the view.
To see what I'm referring to load the "Phone" app on your iPhone and you can type in a number on the keypad, switch tabs, switch back to the keypad and the number you typed remains there. Which is a desirable trait for the Phone app, but not so much for what I'm designing.
Is there a way to achieve this? Or, should I use another method to update my views when tabs are switched?
I think Neil Galiaskarov comment that you should not think about releasing the view. His idea to put your current reloading logics in -(void)viewWillAppear is sound:
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppeared:animated];
// Any code you are currently triggering in your init / viewDidLoad
// to reload your database and display the result
}
This is triggered every time you return via the tab-bar and should give you the result you are after. There are few caveats however, depending on what you do next, that might not deliver the required functionality:
The screen will be updated when it is reached by popping the stack (which is probably OK from what you are describing).
If you start to navigate backwards in the stack with the swipe-gesture but abort the navigation the screen will also be updated. (As this triggers viewWillAppear and viewDidAppear).
If the latter is a problem one way to handle it through a BOOL _shouldTriggerReload;:
Wrap the viewWillAppear logic inside an if:
if (_shouldTriggerReload){
_shouldTriggerReload = NO; // Preparing for the next round
// Any code you are currently triggering in your init / viewDidLoad
// to reload your database and display the result
}
Then in your viewDidDisappear:
- (void)viewDidDisappear:(BOOL)animated{
[super viewDidDisappear:animated];
_shouldTriggerReload = YES;
}
And it will also have to be set inside your viewDidLoad for that first entry:
- (void)viewDidLoad{
_shouldTriggerReload = YES;
}
tabBarController has a viewControllers property.
You modify the viewControllers property to achieve such effect.
What i would do is,
For the view controller(say VC) which you want to reload its view, when user selects that tab.
add UITabBarControllerDelegate delegate to VC. and implement below method.
– tabBarController:shouldSelectViewController:
when the user selects this in bottom tab bar, tabBarController calls this method whether should it show this viewController or not.
Here, change the tabBarController.viewControllers property and return YES.
Lets say your tab bar has only two viewControllers attached to it, and user now selects tab 2 and you have to create new viewController and show it.
So,
UITabBarController *tabBarController;
NSMutableArray *array=[NSMutableArray arrayWithArray:tabBarController.viewControllers];
UIViewController *viewController2; //init your viewController type 2
[array replaceObjectAtIndex:1 withObject:viewController2];
tabBarController.viewControllers =[NSArray arrayWithArray:array];
Use delegate method
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
Add your piece of code which you can trigger each time whenever you select tabBarItem.
I have an iPhone application which consists of two View Controllers; a main one, and one with the help screen. Each one has a button that performs the segue from one to the other.
The problem I have is, when I segue back from the help screen to the main screen, the main view controller's viewDidLoad method gets called, so all of the initialization I did when the app was first started is repeated. Is there another method in the view controller that gets called just once, where I can do the initialization?
My first thought was, "Have a boolean variable that is initially set to false, then have viewDidLoad test it, and if it is false, do the initialization, then set it to true" - but how do I initialize it to false in the first place?
My guess is that you're doing a "Push" segue (which is the most standard kind of segue one can do in an iOS app), and if you are using a "Push" segue that means you have a navigation controller in your app.
The best thing to do here is not to push another "Main" view controller onto the stack of other view controllers (which is why you are seeing "viewDidLoad" called each time you push the main view), but instead when you click a "go to main" button in your help screen, pop the help screen off and return to the previous one. The call that would do this is UINavigationController's popViewControllerAnimated method.
Doing that means "viewDidLoad" on that view controller only gets called once, as the main view gets loaded once.
on the .m class file create a bool on #implementaition:
#implementation yourClass{
bool initialize = 0;
}
and then test it on view did load:
-(void)viewDidLoad{
if(initialize == 0){
//do everything you need to do
initialize = 1;
}
}
I think it will work...
I got two viewControllers using a navigation bar. The first viewController displays some data I change on the second viewController.
So if I load the second viewController, a back button appears in the NavBar and I can change my values (and they are stored, I used the debugger). My problem is, after hitting the backButton to come to my firstView Controller, it does not call it's viewDidLoad method. It's clear, that there are no updated values at all, when this function is not called.
At the first start, the viewDidLoad method is called and does what I want it to do. After going back and forth between the viewControllers the method is not called again.
Any solutions?
Thanks!
EDIT:
SOLVED
I did not want to delete my question, maybe someone needs this too:
This method is called every time the view appears, it is probably not defined by default:
-(void)viewDidAppear:(BOOL)animated
{
NSLog(#"View appeared.");
}
But the update code (like [[self view] setNeedsDisplay];) in viewWillAppear.
To make it clear: viewDidLoad is called when your view is loaded. This happens at the first time the view is going to be displayed. When you then navigate to the next view the first view can (depending on your code) still be loaded. Therefore when you navigate back to that view viewDidLoad won't be called because the view is still there.
But every time the view is going to be shown (for example when you navigate back to this view) the method viewWillAppear and viewDidAppear will be called.
Hope that helps.
ViewDidLoad method will get called when there is view controller allocation-initialization happens. In the case of moving back in navigation controller, it is not creating any new view controllers, it is reusing previous references from navigation stack.
Hence viewDidLoad will not get called. As your view controller is already in memory stack. So it will just make the view to reappear on windows and it will call viewWillAppear respectively.