I've a GLKViewController which renders an OpenGL 2.0 scene. All works fine, but when I segue to a new storyboard scene (via a UINav Controller) and then return to the OpenGL ES 2.0 scene, the update and drawRect methods in the view controller are no longer called.
I've tried setting self.paused to NO in the viewDidLoad method, but to no avail.
Can anyone suggest what is happening here ?
The GLKViewController contains a UIView, both of which are set in the storyboard. This is the segue to the view from the GLKViewController :
if ([segue.identifier isEqualToString:#"GoToEntry"]) {
DetailViewController *d = segue.destinationViewController;
d.selection = currentSelection;
}
Ok - the problem was that GLKViewController sets paused to YES when view exits. viewWillAppear wasn't actually being called - moving self.paused to viewDidAppear solved the problem.
Related
In my app, sometimes pushViewController fails for no reason and what happens is very weird. The navigationBar and navigationItem change but the ViewController is not pushed. Then I can tap nothing on the screen. I find that viewWillAppear is called but viewDidAppear isn't called. I push the home button of iPhone to enter background. After entering foreground again, the ViewController is pushed and viewDidAppear is called. I don't know why and when it happens.
normal viewDidAppear callstack
viewDidAppear after enterBackground callstack
If you can repro by:
Try using the left edge pop gesture when there are no view
controllers below it (i.e on root view controllers, your VC-Home
controller)
Try clicking on any UI elements after this.
Then Disable interactivePopGestureRecognizer when current viewController is the firstVC in navigation controller.
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
self.navigationController.interactivePopGestureRecognizer.enabled = YES;
}
reference:
iOS App Freezes on PushViewController
Is the viewcontroller which you pushed into the view hierarchy overwrite the viewWillAppear/viewDidAppear accidently without calling [super viewWillAppear/viewDidAppear:animated]?
You're probably accidentally calling [super viewDidLoad] inside your viewWillAppear method
For anyone having the same issue as me: Check all your custom views to see if you're not having an infinite loop of layoutSubviews. This is on of the things that happens in between a viewWillAppear and a viewDidAppear.
In my implementation I had a custom Tab bar controller and fore some reason viewDid Appear was empty, putting super calling solved it.
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated) //was missing this line
}
You know,if you overwrite navigationController.interactivePopGestureRecognizer.delegate and not restore it appropriately, this bug will appear,too
I have a UIViewController class that contains a WKWebView and implements WKNavigationDelegate.
I would like to detect when a the view controller appears again. I understand the method loadView but, if I push a new view on the stack and then go back from that view to the previous view (my view controller) which method is called on the view controller?
The method that will be called is viewWillAppear:.
If you push to next view then viewDidLoad will be called first
Then viewWillAppear, viewDidAppear
If you pop to previous screen again (your UIViewController) then
viewWillAppear will be called first and after entire view appears
then viewDidAppear will be called..
viewDidAppear is useful in the cases where any method called at viewWillAppear after that you can Load the data at ViewDidAppear..
The ViewControllers viewDidLoad method is only called once when the view is created for the first time.
// viewDidLoad is called only once when the view is created for the first time
- (void) viewDidLoad
{
[super viewDidLoad];
// do your code here
}
You can also implement the below two methods in side your ViewController.m class
// viewWillAppear is called just before the view is about to be appeared
- (void) viewWillAppear
{
[super viewWillAppear];
// do your code here
}
// is called when the view has appeared
- (void) viewDidAppear
{
[super viewDidAppear];
// do your code here
}
I'm trying to add a UIKit ViewController on top of a cocos2d scene. Everything works great, but I need to run [[CCDirector sharedDirector] stopAnimation] AFTER the UIKit view is loaded completely.
I push a button and have a 1 second transition to the new scene being loaded. I have tried adding stopAnimation to every callback in both the UIViewController(ViewDidLoad, ViewDidLayoutSubviews, etc) and the Cocos2d scene. What happens is the scene is loaded but the animation is stopped before the UIViewController is completely loaded, which prevents the view from loading at all.
I could set a timer for the transition duration and then call stopAnimation but I would rather not do it that way. Is there any sort of delegate method I'm missing here?
You need to call that method from your view controller's viewDidLoad method:
- (void) viewDidLoad
{
[super viewDidLoad];
[[CCDirector sharedDirector]stopAnimation];
}
I noticed some strange behavior when passing data to a popover in iOS 5. The Popovers viewDidLoad method is called before prepareForSegue is called:
In Storyboard a segue connects a button of FirstViewController to PopoverViewController, which is embedded in a Navigation Controller.
For testing the two methods are logged:
/* FirstViewController.m */
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showPopover"]) {
NSLog(#"FirstViewController: prepareForSegue");
UINavigationController *navigationController = segue.destinationViewController;
PopoverViewController *popoverVC = (PopoverViewController *)navigationController.topViewController;
popoverVC.myProperty = #"Data to be passed";
}
}
and in the other ViewController:
/* PopoverViewController.m */
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"PopoverViewController: viewDidLoad");
}
Under iOS 6 the behavior is as expected:
2013-02-25 09:03:53.747 FirstViewController: prepareForSegue
2013-02-25 09:03:53.751 PopoverViewController: viewDidLoad
Under iOS 5 viewDidLoad of the PopoverViewController is called before prepareForSegue:
2013-02-25 09:05:28.723 PopoverViewController: viewDidLoad
2013-02-25 09:05:28.726 FirstViewController: prepareForSegue
This is strange and makes it hard to pass data to the Popover which can be used in viewDidLoad. Is there any solution to this?
I solved the problem now using the viewWillAppear: method instead of viewDidLoad. I think this is the better method for configuring views anyway (as the view could be already loaded and the view should be configured on every appear).
The viewWillAppear: method is loaded after the prepareForSegue in iOS 5 and iOS 6.
However, for those needing viewDidLoad the solution suggested by tkanzakic is the one that works then.
create a custom setter for your property and perform the operations you need from there, I use to do it in this way:
- (void)setCity:(GLQCity *)city
{
if (_city != city) {
_city = city;
[self configureView];
}
}
- (void)configureView
{
if (self.city) {
...
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
...
[self configureView];
}
I don't know anything about the differences between iOS 5 and 6, but I had run into similar confusions in the past. If you follow the general rules of thumb:
prepareForSegue is called before destination VC's viewDidLoad
viewDidLoad is called only after ALL outlets are loaded
Therefore, do not attempt to reference any destination VC's outlets in source VC's prepareForSegue.
Then, you would naturally arrived at either solutions - implement viewDidAppear vs. viewDidLoad, or set destination VC's properties only vs. touching any of its outlets.
Another lesson learned with regards to prepareForSegue is to avoid redundant processing. For example, if you already segue a tableView cell to a VC via storyboard, you could run into similar race condition if you attempt to process BOTH tableView:didSelectRowAtIndexPath and prepareForSegue. One can avoid such by either utilizing manual segue or forgo any processing at didSelectRowAtIndexPath.
I've created a project from the master detail template in Xcode 4.2/iOS5. I am trying to preform a modal segue from the splitviewcontroller. I call the following from my detailviewcontroller.m:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self.splitViewController performSegueWithIdentifier:#"DisplayLoginView" sender:self.splitViewController];
}
The login view shows fine but it does not rotate and stays in portrait. Any ideas on how to get it to autorotate?
I fixed this by implementing a custom class for the destination view controller and adding the
shouldAutorotateToInterfaceOrientation: method making sure it returned YES.