I am using pushViewController to push a view in my application. Pressing the back button works about 95% of the time like you would expect. But if I go in and out of the view as fast as possible I run into a condition where the top bar moves as if a pop has occurred, but the view says. In this state, I am left with a back button, (in normal operation I have changed the text of this button to 'cancel'). pressing back will animate the top bar again, and then I am left with no buttons in the top bar, and I'm stuck inside the view.
Do you have any idea what might be going on here? Here are some more details:
The sub view calls these once or twice:
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
also the sub view is extending a BaseViewController. Inside this base controller all of the view methods are overloaded (they just call super). The one that might be interesting is:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self customizeNavigationBar];
}
- (void)customizeNavigationBar
{
[self.navigationController.navigationBar setTintColor:UIColorFromRGB(kNavigationBackgroundColor)];
UIBarButtonItem *backButton_ = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(#"ID_BUTTON_BACK", #"") style:UIBarButtonItemStyleBordered target:self action:nil];
self.navigationItem.backBarButtonItem = backButton_;
[backButton_ release];
}
Please let me know if you need more code or if I can explain things better.
--- Edit ----
I also am calling Google Analytics in view will appear. I remember this causing other issues in my app:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSError *error;
if (![[GANTracker sharedTracker] trackPageview:#"/app_new_page"
withError:&error]) { }
}
This code is being put in my actual view (not BaseViewController).
I found the problem. The issue was that I was calling setNavigationBarHidden:NO with animated:NO in viewDidLoad to show the nav bar without animation, but using pushViewContoller with animated:YES.
----- originally -----
[self.navigationController pushViewController:controller animated:YES];
and
- (void)viewDidLoad
{
[super viewDidLoad];
[self.navigationController setNavigationBarHidden:NO animated:NO];
}
The solution was to remove setNavigationBarHidden from viewDidLoad and move it into viewWillAppear, and to animate it the same way the view was animated. Since my nav bar was appearing instantly, it was possible to press back before the view controller had finished animating (pushing onto the stack), causing all these issues.
----- solution -----
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:NO animated:animated];
}
Thanks for your help guys!
Related
I tried to add a second splash screen to iOS existing project, this project was too old and using xib's.
So i was planning to show default splash screen first and then my own one image as splash screen after that login page.
This is what i have done so far
In my ViewController.m file i have created on UIView and added one UIImageView its working but the problem is i can see navigationbar also along with second splash screen .
I dont want that navigation bar.
Please help me
Code
ViewController.m in ViewDidload ()
self.navigationController.navigationBar.hidden=YES;
_splash.frame=CGRectMake(0,0,self.view.frame.size.width,self.view.frame.size.height);
_splashImg.frame=_splash.frame;
[self.view insertSubview:_splash aboveSubview:_loginView];
[NSTimer scheduledTimerWithTimeInterval:3.0f target:self selector:#selector(runMethod) userInfo:nil repeats:NO];
[self.view addSubview:_splashView];
[self.view bringSubviewToFront:_splashView];
UIImageView *img=[[UIImageView alloc]initWithImage:[UIImage imageNamed:#"rss2.png"]];
img.frame=_splashView.frame;
[_splashView addSubview:img];
Apple allows only one splash screen per project. You can show your custom image as a splash by creating a new view controller. Say SplashViewController. Add an imageView on SplashViewController's view and set your splash image.
Load SplashViewController when you want to show your custom splash.
In SplashViewController's ViewDidLoad:
- (void)viewDidLoad{
[[self navigationController] setNavigationBarHidden:YES animated:YES];
[self performSelector:#selector(loadingNextView)
withObject:nil afterDelay:3.0f];
}
method to load next view
- (void)loadingNextView{
// write code for pushing VC.
}
In your next view controller's ViewDidLoad show navigation bar
[[self navigationController] setNavigationBarHidden:YES animated:YES];
try this
To hide the navigation bar:
[[self navigationController] setNavigationBarHidden:YES animated:YES];
To show it:
[[self navigationController] setNavigationBarHidden:NO animated:YES];
else
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:YES]; //it hides
}
-(void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
[self.navigationController setNavigationBarHidden:NO]; // it shows
}
There's currently no 'official' way to have a second splash screen, so what you're doing is the way to go. The only suggestion I have for you is to add your custom splash screen view to a window instead of the view controller's view. Adding it to the window (and sizing it accordingly) will make your custom view stand above everything else. You might even create a new window and place it at the UIStatusBar level for a similar, cleaner, effect.
Edit: adding sample code
For the simplest solution
UIWindow *window = [UIApplication sharedApplication].delegate.window;
_splash.frame = window.bounds;
[window addSubview:_splash];
...
// later, when you're done
[_splash removeFromSuperview];
For the slightly more complex, but more elegant, solution of creating a new window, please read the UIWindow documentation.
In the AppDelegate You set the navigation controller as a root view controller in that replace with you just do create the UIViewController as a root viewcontroller.
After few second you just do as a performSelector thru change the root view controller to navigation controller and your problem has been resolve.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
SplashScreenController *viewCon=[[SplashScreenController alloc]
initWithNibName:#"SplashScreenController"
bundle:nil];
self.window.rootViewController= viewCon;
[self.window makeKeyAndVisible];
[self performSelector:#selector(loadNavigationController)
withObject:nil afterDelay:0.2f];
}
-(void)loadNavigationController{
HomeController *viewCon=[[HomeController alloc]
initWithNibName:#"HomeController"
bundle:nil];
self.nav=[[UINavigationController alloc]initWithRootViewController:viewCon];
self.window.rootViewController= self.nav;
}
May this help to ease to solve your problem.
I have a problem where a navigation bar suddenly appear after popViewController is called when SearchDisplayCotroller is still active.
I am implementing a simple tableview with searching capability. Above is my storyboard.
On the first view, i've implemented as per below. So, the navigation bar will be always hidden for the first view.
- (void) viewWillAppear:(BOOL)animated{
[self.navigationController setNavigationBarHidden:YES animated:NO];
}
Button press will push the next table view controller with the below code so that the navigation bar will be visible.
- (void) viewWillAppear:(BOOL)animated{
[self.navigationController setNavigationBarHidden:NO animated:NO];
}
Everything works fine until i implemented the below code.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.navigationController popViewControllerAnimated:YES];
}
When popViewControllerAnimated:YES while the SearchDisplayController is still active, a weird white navigation bar appears and my viewWillAppear is unable to hide the bar. Is this a bug or is there any way to prevent this bar from appearing?
The gif below may also give you the idea what did happen. Thanks!
Try this
-(void) viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
// To check if searchDisplayController still active
if ([searchDisplayController isActive]) {
[searchDisplayController setActive:NO];
}
}
Try inactivating your UISearchDisplayController by calling setActive:NO animated:NO before you call [self.navigationController popViewControllerAnimated:YES];
https://developer.apple.com/LIBRARY/IOS/documentation/UIKit/Reference/UISearchDisplayController_Class/index.html#//apple_ref/occ/instm/UISearchDisplayController/setActive:animated:
This is the situation...
I have UIViewController, I want to programatically, without any buttons, to go to my Tab Bar Controller or to one of my Table View Controllers.
This is what I did so far:
UIViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
[self dismissViewControllerAnimated:NO completion:^{
[self performSegueWithIdentifier:#"appLaunched" sender:self];}];
}
This does not work, I made a segue and gave it an id, but the issue remains, my app when launches just shows a white screen and the transition is never made. Can anyone help me please?
Thank you.
Perhaps try something like
- (void)viewDidLoad
{
[super viewDidLoad];
[self pushIt];
}
- (void)pushIt
{
[self.navigationController pushViewController:[self.storyboard instantiateViewControllerWithIdentifier:#"appLaunched"] animated:YES];
}
I am using navigation controller in my application. Mostly all controllers have navigation bar hidden false except in one controller. When I pop from that controller then navigation bar is shown weird and the bottom space of about navigation bar is left. Also when I do start editing or do some selection or something else the navigation bar becomes normal and the empty space is removed, but it remains till I don't do anything. I am using Xcode 5, and these happens in both iOS 6 and ios 7 not tested in iOS 5. In view Did disappear of that controller I do
self.navigationController.navigationBar.hidden = FALSE;
[self.navigationController setNavigationBarHidden:NO];
Also in view will appear of the other controller I have written
self.navigationController.navigationBar.hidden = FALSE;
[self.navigationController setNavigationBarHidden:NO];
In both the view auto layout is false as I need to change frame dynamically on different conditions. Please help.
Use below code.
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:YES animated:animated];
}
- (void) viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.navigationController setNavigationBarHidden:NO animated:animated];
}
Use willAppear/Disappear instead.
In my case i removed that white space by setting background color of the navigation bar view. like
[[[self navigationController] view] setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"background.png"]]];
On View1 I hide the navigationBar in viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
[self.navigationController setNavigationBarHidden:YES];
}
Then I navigate to View2 where I show the navigationBar
- (void)viewDidLoad
{
[super viewDidLoad];
[self.navigationController setNavigationBarHidden:NO];
self.title = #"Title";
}
But on back to View1 again, the navigationBar doesn't hide, even if I did tried to hide it after the pushViewController in View2
[self.navigationController pushViewController:View1 animated:YES];
[self.navigationController setNavigationBarHidden:YES];
I also tried to hide the navigation from viewWillAppear in View1 and it hides it, but there is an ugly delay and I don't find it as a good practice.
So can anyone help me with this issue, how can I hide correctly the navigationBar on back to View1?
The best practice to do what you want is putting bellow in your first viewController:
- (void)viewWillAppear:(BOOL)animated{
[self.navigationController setNavigationBarHidden:YES animated:animated];
[super viewWillAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated{
[self.navigationController setNavigationBarHidden:NO animated:animated];
[super viewWillDisappear:animated];
}
-(void) viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self.navigationController setNavigationBarHidden:YES];
}
The ViewController1 is not going to get allocated again and so viewDidLoad is not going to get called.
You can do it in viewWillAppear though. But if you are saying that there is a delay, you can do one more thing.
You can get the reference ofViewController1 in ViewController2. Suppose ViewController1 is the first controller in the navigation controller, then do this:
//ViewController2.m
- (IBAction)backButtonPressed:(id)sender{
ViewController1 *view1 = [self.navigationController.viewControllers objectAtIndex:0];
[view1.navigationController setNavigationBarHidden:YES];
Your code is correct, but you need to write like this:
[self.navigationController setNavigationBarHidden:YES];
first, then write
[self.navigationController pushViewController:View1 animated:YES];
See when you are pushing View2 from View2 in navigation stack than View1 doesn't gets deallocated. it is there in in the stack. So when you popping out View2 that time View1 viewDidLoad won't get called. so your code setNavigationBarHidden to hide navigation bar doesn't executes. So put that code to ViewWillAppear or ViewDidAppear because these methods gets called every time View appears.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:YES];
}