In my ios app, I begin by loading the SecondViewController using the code shown below. When that view controller appears, I also run viewDidAppear as shown in the code snippet below.
That works ok. From there, I load my FifthViewController and do some calculating which needs to be returned to the SecondViewController.
Unfortunately, when I return to SecondViewController via the same exact method, the viewDidAppear method does not run.
Any suggestions on how to fix that would be appreciated.
-(IBAction) loadSecondView:(id)sender
{
NSLog(#"In loadSecondView method \n");
[secondViewController viewDidAppear:YES];
[self clearView];
[self.view insertSubview:secondViewController.view atIndex:1];
}
If you want something to be performed every time after dismissing a viewcontroller, you should use delegate method. It is much more specific than viewDidAppear or viewWillAppear.
Here's a website where you can get started.
Related
I'm developing an application which will work based on maps. So once user opens MapViewController then I will load some data every 5 seconds.
I'm using navigation controller(Push view controller).
So every time when user goes to MapViewController viewdidload method calling. I don't want like that.
That's why I'm trying to avoid viewdidload method like tabbarcontroller.
Is there any way to achieve this?
viewDidLoad is getting called because your MapViewController is getting deallocated when you pop it off of the top of your navigation controller. When you recreate the view controller, it's getting allocated all over again, and the view loads again. If you keep a reference to MapViewController in the class containing your navigation controller, then ARC will not deallocate the object, and you can use this reference to push it back onto the stack so viewDidLoad will not get called again.
Edit: Adding code for reference:
MapViewContoller *mapViewController; // declared globally so there's a strong reference.
- (void) openMapViewController {
if (!mapViewController) {
mapViewController = [self.storyboard instantiateViewControllerWithIdentifier: MapViewControllerID];
}
[self.navigationController pushViewController: mapViewController, animated: YES];
}
Try this
-(void)clickForPush{
// declarre viewcontroller e.g 'saveRecipeVC' instance globally in interface
if (!saveRecipeVC) {
saveRecipeVC = [self.storyboard instantiateViewControllerWithIdentifier:SaveRecipeVCID];
}
[self.navigationController pushViewController:saveRecipeVC animated:YES];
}
viewDidLoad is intended to use when,not possible or efficient to configure 100% of an interface in a XIB. Sometimes, a particular property you wish to set on a view isn't available in a XIB. Sometimes, you use auto layout, and you realize that the editor for that is actually worse than writing auto layout code. Sometimes, you need to modify an image before you set it as the background of a button.
If you dont want to do these things make your viewDidLoad empty. Than avoiding. Or
Add code conditionaly into your viewDidLoad.
(void)viewDidLoad {
[super viewDidLoad];
if(condition) {
// put your code here
}
}
I'm implementing my own 'back' button. Where onClick, the following code is executed in the ViewController (VC) being dismissed:
Dismiss current VC (VC#1)
Pop current VC (VC#1) off my custom navigationStack
Get the last VC (VC#2) from the navigationStack, and present it using
presentViewController
What happens is the back works visually works - i.e. current VC disappears, previous VC appears. However, the viewDidLoad method is not called. So the screen isn't updated with data updates from viewDidLoad.
[self dismissCurrentViewController:self completion:^{
[TWStatus dismiss];
FHBaseViewController *vcToDisplay = [[FHDataManager sharedInstance] popNavigationStack];
[vcToDisplay.homeVC presentViewController:vcToDisplay animated:NO completion: ^{ }];
}];
Questions:
I was under the impression that viewDidLoad always gets called when presentViuewController is used??
I 'build' the screen using a method called ONLY from viewDidLoad in VC#2. How is iOS displaying the screen without coming into viewDidLoad?
btw, I'm not using storyboards. Any help is appreciated!
My guess is that viewWillAppear is being called but viewDidLoad is not, at least not when you expect it is. viewDidLoad should be called once, but depending on how you're managing the view controllers, viewDidLoad may not be triggered every time your view appears (which happens after loading).
The completion handler is called after the viewDidAppear: method is called on the presented view controller. from presentViewController doc
so put this in your code with a breakpoint on the call to super and verify it is getting called when this transition occurs.
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}
edit: since you verified that viewWillAppear is getting called, then I would say that it's coming down to how you are managing the view controller life cycle. Even with a standard UINavigationController, viewDidLoad is not called when a view is shown as a result of popping items on the navigation stack. I would move your logic to viewWillAppear if you are dead set on not using UINavigationController
When I make a back button pragmatically I use:
[self.navigationController popViewControllerAnimated:YES];
This will invoke the viewDidLoad method. Use that instead of your current code.
i have used master-detail view in my application.
when videos row is selected in master view , the videos method is called and it is as shown above, in the videos method i am writing code to dismiss the popover and calling a method fetchvideosfromurl: , but during execution the method fetchvideosfromurl is being executed first and after that the popover dismisses, but i want the popover to be dismissed before the method is called, how to do it. Thank you
you can do the following:
-(void)videos
{
[popover dismissPopoverAnimated:NO];
[self performSelector(loadUrl) withobject:nil afterDelay:2.0];
}
-()loadUrl
{
//code in the following Image
}
hope this will help you.
I've a bunch of turn based games in my app, and I use the same animations to declare the starting player.
At the very end of viewDidLoad, I placed the code for declaration. It takes the screenshot of current view then blurs it a little, and labels appear to show the name of the starting player. The issue is sometimes it happens to fast that I got the screenshot of previous view and labels appear on the blurred screenshot of previous view.
My viewDidLoad looks like this:
-(void) viewDidLoad
{
[super viewDidLoad];
[self initializeThings];
[self layoutUI]; //In some of the games this part requires heavy processing,
//ie laying out a 2D array of buttons (20x20=400 of them)
[self showStartingPlayer];
}
I use the default transition style cover vertical in all VCs. I tried calling [self showStartingPlayer]; deferred by using performSelector with delay but different devices require different delay values so it is not a robust solution. Is there any other method I can use in viewcontroller lifecycle instead of viewDidLoad or any practical way of doing such a thing?
if you are using presentViewController: animated: completion:, i would take advantage of the completion block to notify the view controller that the transition is complete.
for example, you could add a public method called -(void)wasJustPresented to your view controller which calls the necessary UI layout.
Then, call this in your completion block. Ex:
[self presentViewController:newVC
animated:YES
completion:^(void){
[newVC wasJustPresented];
}];
This will ensure your view controller is notified right after it is done being presented.
viewDidLoad is called when the view of the view controller has been loaded, but it doesn't mean that it's actually visible on the screen.
You may use - (void) viewDidAppear: to do that.
You should try to call your method inside the viewDidAppear which is called as the view transition has finished.
-(void)viewDidAppear:animated
{
[super viewDidAppear:animated];
//put your call here
}
I need to load some data into a view every time it is shown. The data changes, each time time view is shown, so I figure I can load the data in the method viewDidAppear. Unfortunately, I've found that viewDidAppear is not called each time the view is displayed.
The code that displays the view from any other view is....
[self clearView];
[self.view insertSubview:fifthViewController.view atIndex:4];
So I figured I could change it to the following to run viewDidAppear...
[[self.view insertSubview:fifthViewController.view atIndex: 4 viewDidAppear:YES];
Unfortunaely, this causes an error "bad receiver type 'void'
What do I need to do to insert the subview and also call viewDidAppear?
If you show the view by modifying ViewController.view visibility directly, you won't get viewDidAppear message by that. You need to use ViewController method to display the view, e.g. push controller into UINavigationController or using presentModalViewController method. You can use the hack like calling viewWillAppear: and viewDidAppear: manually, but I don't like the idea.
Thank you for the assistance with this question.
I have settled on the addition of a viewDidAppear in the method that inserts the subview.
Below is the code that is working for me at this time.
In the .m file of the highest level view controller, the following code sets up the viewDidAppear call and then inserts the fifth subview.
-(IBAction) loadFifthView:(id)sender
{
[fifthViewController viewDidAppear:YES]; // sets up viewDidAppear
[self clearView];
[self.view insertSubview:fifthViewController.view atIndex:4];
}
With the above code snippet in place, the following code snippet, located in the .m file of the fifth view controller reports that it is working.
- (void)viewDidAppear:(BOOL)animated
{
NSLog(#" xxxxxxxxxxxxxxxx inside viewDidAppear ");
}