9

There are several similar questions which got no answers but were describe vaguely. I have reduced the problem into a very thin application, and added detailed screenshots. I would highly appreciate a solution for this!

The only involved code is one line added to viewDidLoad of the root VC. The purpose of this line is to make the navigation controller opaque:

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.navigationController.navigationBar.translucent = NO;
}

A critical information for this question is that 'Title1' has a prompt in its navigation item, while 'Title2' has not prompt.

I have a storyboard with one navigation controller, one root VC called "Title1", with a segue button which takes to a second VC called "Title2"

storyboard


When pressing the button here:

pre press


I'm getting this strange screen:

after press


When pressing back (Title1), it gets worse (i.e.: the original label of Title1 was pushed up and now not being seen anymore!!!):

after back

Anyone please??

ishahak
  • 6,585
  • 5
  • 38
  • 56

5 Answers5

3

It appeared as translucent property of UINavigationBar appeared to be messed up with frame other view controllers.

I would recommend following approach.

Create a base view controller from which other view controllers will inherit as follows,

#import "BaseViewController.h"

@interface BaseViewController ()

@end

@implementation BaseViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.navigationController.navigationBar.translucent = NO;
}

other view controllers will inherit above BaseViewController

// interface

#import <UIKit/UIKit.h>
#import "BaseViewController.h"

@interface ViewController : BaseViewController

@end

// implementation

#import "ViewController.h"

@implementation ViewController

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    // Here translucent property is enabled when the view is about to be disappeared.
    // However note that, translucent property needs to be enabled only on those view controllers which has prompt set on their navigation items.
    self.navigationController.navigationBar.translucent = YES;
}

Other view controllers without prompt implementation will work as usual however they also needs to inherit from BaseViewController.

ldindu
  • 4,270
  • 2
  • 20
  • 24
  • Thank you @Idindu. I need to check your approach, but not sure I'm following you. For my app, even without a prompt, the translucency must be set to NO, because I need the content to appear below the navigation bar – ishahak Jan 12 '14 at 14:35
  • Yes, I am just setting it to NO, for the view controller which has its prompt set, when the view controller is about to disappear but since it is set again in BaseViewController which you other view controllers will inherit from. – ldindu Jan 12 '14 at 16:28
  • setting navigationController.navigationBar.isTranslucent = true was the fix that worked for me – Tinkerbell Jan 15 '17 at 12:20
3

Late answer but I stumbled across this problem today and found your question and it doesn't have an accepted answer yet.

I got this error while going from a prompted viewController to a non prompted viewController in storyboard.

I got that black bar just like you.

And to fix:

// In prompted vc
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    UIView.setAnimationsEnabled(false)
    self.navigationItem.prompt = nil
    UIView.setAnimationsEnabled(true)
}

This will remove the prompt instantly before switching viewcontroller.

UPDATE

func prompt() -> String? {
    return nil
}

override func viewWillAppear(animated: Bool) {
    let action = { self.navigationItem.prompt = self.prompt() }
    
    if self.navigationController?.viewControllers.count <= 1 {
        UIView.performWithoutAnimation(action)
    }
    else {
        action()
    }
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {        
    UIView.performWithoutAnimation {
        self.navigationItem.prompt = (segue.destinationViewController as? ViewController)?.prompt()
    }
}
Community
  • 1
  • 1
Arbitur
  • 38,684
  • 22
  • 91
  • 128
  • This only works if you segue to another view. In the case of a navbar and the back button a segue is not executed. Tried putting that code in viewWillDisappear with no luck – lostintranslation May 23 '16 at 20:25
  • @lostintranslation thats because u need to put it into `viewWillAppear` in the VC u're backing to. Ill update my answer – Arbitur May 24 '16 at 08:45
3

The best way to solve this issue is setting the background of the window during push i.e,

let appdelegate = UIApplication.shared.delegate as! AppDelegate
appdelegate.window?.backgroundColor = UIColor.white
puneeth
  • 743
  • 7
  • 8
1

Seems like Xcode has some issues when changing the navigationBar height since main controller view is not resized accordingly.

I found a solution to do this, not sure it is the best... but it's working.

Just inherit your viewWillAppear and viewWillDisappear methods in your first view controller (the one with a prompt):

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    self.navigationItem.prompt = @"Prompt1";

    [UIView animateWithDuration:UINavigationControllerHideShowBarDuration
                          delay:0.0
                        options: UIViewAnimationOptionCurveEaseOut
                     animations:^{
                         [self.view setFrame:CGRectMake(0, 94, 320, 386)];
                     }
                     completion:^(BOOL finished){
                     }];

}

- (void) viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];

    // Sets prompt to nil
    self.navigationItem.prompt = nil;

    [UIView animateWithDuration:UINavigationControllerHideShowBarDuration
                          delay:0.0
                        options: UIViewAnimationOptionCurveEaseOut
                     animations:^{
                         [self.view setFrame:CGRectMake(0, 64, 320, 416)];
                     }
                     completion:^(BOOL finished){
                     }];
}

I didn't focus on frame size (it's for 3,5" iPhone frame sizes). You must calculate this size or you might have some issues with larger screens.

Damien
  • 660
  • 6
  • 15
  • Hi @Damien, really appreciating your solution. The real application has many screens so it surely not a neat solution, so I'll wait to see if any better one appears – ishahak Jan 12 '14 at 13:15
0

The top answer on this thread just solved this problem for me, thank you.

Here's the thing, the app I'm working on uses coordinators and autolayout, so looking at this showed the animation need to be shut off. I had to change the navigation controller's push view controller function's animate parameter to false.

Ex:

navigationController?.pushViewController(view, animated: false)
Tristan Newman
  • 357
  • 1
  • 4
  • 13