iOS 10 - View Controller / Navigation Bar Title hidden - ios

I'm currently facing stranges behaviours with iOS 10.
Indeed, everything was working fine, but since I updated to xCode 8 and began testing my App on iOS 10, a lot of stuff went wrong.
For example, all my Navigation Bar's titles are not displayed anymore.
More precisely, when I'm using the menu to navigate threw my app, every time I switch to a different view, there are no title, BUT when I press the back button, I can briefly see it before the transition to the other view.
I don't understand this new behaviour, I didn't change anything in the code, and when I launch the App on iOS 9 or lesser, everything is working properly.
I tried to set the title in the ViewWillAppear / ViewDidLoad, in the prepareForSegue, but nothing is working.
if ([segue.identifier isEqualToString:kMy_Segue]) {
MyViewController* destinationVC = segue.destinationViewController;
[destinationVC setTitle:#"MyTitle"];
}
I feel like there are some changes with the pushed Navigation Controller, or the title item is not at the same index than the Navigation Bar itself because when I navigate threw subviews in the menu, the title only appears when I press back.
For example I have a category in my Menu called "World".
When I tap it I want the title of the subview to be "World", but nothing is displayed. Then, I have all the continents listed "Africa", "Europe", "Asia" etc...
When I tap on Africa, I want the next title to be "Africa" right?
And again, nothing is displayed BUT if I press the back button and go back to the list of continents, the title "World" appears.
If anyone has encountered this issue, I would really appreciate some help.

Follow this:
Solution-1
Goto to the viewController, then click on NavigationItem as shown below:
In the right pane, change "Title" as follows:
Solution-2
Add a UIView to your navigationBar as shown below:
Add an UILabel to your navigationItem as shown below:
Change the frame of the newly added UILabel as follows:
Change text of UILabel to "Sample Title" and change UIView backgroundColor to clearColor.
I have made a sample in Xcode8, please check my GitHub link below:
https://github.com/k-sathireddy/NavigationItemSample

Have you try to adding navigation item on to your navigation bar? You'r using Storyboard for this design.

I found a solution to my issue. It's really weird.
I have a fade animation to the navigation bar on the Home Page.
It's a scroll view so that when I scroll down I can still see the title and the navigation bar.
On iOS < 10, the fade animation only change the background color and transparency. But when I launch the app on iOS 10, the fade effect hide everything, the menu icon, the title, everything. I believe Apple changed the structure of the navigation bar items.
Moreover, when I tap on the menu icon to navigate threw my App when the fade animation is on going, I can see that the title and the navigation bar items are under "fade effect" and even for the next ViewControllers's title after my navigation.
So it's working, it's just that the menu icon, titles etc.. are hidden on the Navigation Bar.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
UIColor * color = [Constants backgroundColor];
CGFloat offsetY = scrollView.contentOffset.y;
CGFloat threshold = 250;
if (offsetY > threshold) {
[self.navigationController.navigationBar lt_setBackgroundColor:[color colorWithAlphaComponent:1]];
} else {
CGFloat alpha = offsetY / threshold;
[self.navigationController.navigationBar lt_setBackgroundColor:[color colorWithAlphaComponent:alpha]];
}
}
I guess the issue is coming from the library LTNavigationBar that I used to change the appearance of the NavigationBar dynamically...

Related

Blank space coming between keyboard and UIVew in iOS

I have a tab bar controller-based application and I am using IQKeyboardManager to handle form-like stuff.
Step 1: Tab bar controller with bottom a UITextView inside a UIView. Check Image 1.
Step2: When I click on UITextView, the keyboard appears but a blank space is appearing due to the tab bar. I have tried to remove IQKeyboardManager but it still occurs, so it is confirmed that it is not the issue of IQKeyboardManager. It is an issue due to the tab bar controller.
How to remove that spacing?
You are correct. The blank space is caused by the tab bar. Override the y position in the view by adding the additional space when you receive keyboard should appear and not in your viewDidLoad or any place else because it will then be hidden behind the tab bar. Then you need to set it back to normal by removing that added value when the user is finished using the keyboard. eg.
// Declaration
var tabBarHeight : CGFloat = 0.0
// viewDidLoad
tabBarHeight = tabBarController?.tabBar.frame.size.height
// When the user begins using the keyboard move the view containing the textfield
yourView.frame.origin.y = (tabBarController?.tabBar.frame.origin.y + tabBarHeight )
// When the user finishes using the keyboard
yourView.frame.origin.y = (tabBarController?.tabBar.frame.origin.y - tabBarHeight )
If you have constraints, you will need to adjust them. Good answer here:
https://stackoverflow.com/a/27870216/4008175
This answer will assist you in listening to when the keyboard has been activated and deactivated:
https://stackoverflow.com/a/27087733/4008175
Good luck!

backBarButtonItem becomes visible on iOS 10 when titleView has constraints

Having a very weird behavior on iOS 10. Assume you have an empty app, created with a Master-Detail Application template. Place any UIView as a titleView in navigationBar for detail viewcontroller. Place any UIView to the right bar button items.
Then, write that code to configureView method:
if let item = self.splitViewController?.displayModeButtonItem {
self.navigationItem.leftBarButtonItem = item
self.navigationItem.leftItemsSupplementBackButton = true
}
Then configure splitviewcontroller preferredDisplayMode = .allVisible, so the displayModeButtonItem could appear.
On iOS 9 and lower this results in a standard behavior: the detail viewcontroller displays displayModeButtonItem expand button on a left side.
When user taps it, the icon transforms to an arrow. Tapping an arrow reverses button state.
On iOS 10 displayModeButtonItem displays as expand button, but if user taps it, it disappears.
Meanwhile, the button is still there and a user can tap it one more time. After that, displayModeButtonItem appears again with expand icon and backButtonItem icon as well. Just like it appears when we push another viewcontroller onto detail's navigationcontroller:
But in that case both of icons acts as displayModeButtonItem.
Is this an iOS bug, or a misconfig? What can I do to get normal button behavior?
Edit: I found out, that everything works as expected, if a titleView (of rightBarButtonItem's view) does not contain any constraints on it's child views. Filed a radar on this.
Edit 2: Some controls (like UIImageView) may implicitly add NSContentSizeLayoutConstraint, so, to prevent this behavior (and prevent the bug above), subclass it and override intrinsicContentSize method like this:
private class NoConstraintsUIImageView: UIImageView {
private override func intrinsicContentSize() -> CGSize {
// prevent implicit NSContentSizeLayoutConstraint adding in updateConstraints
return CGSize(width: UIViewNoIntrinsicMetric, height: UIViewNoIntrinsicMetric)
}
}

iOS 10 Beta makes navigation bar buttons and title disappear on pushViewController

EDIT: Please watch the video of my issue here:
https://www.dropbox.com/sh/lzgs9mahx5mea13/AADLYfLQix7MDleDN1ER81qVa?dl=0
I have had an app live in app store which works perfectly fine on iOS 9.
However on iOS 10 (tested on device iPhone 6s with latest beta), when the cell on the master view controller is selected and the detail view is "pushed", my navigation bar's title and navigation bar buttons disappear.
Only the back button is visible.
Even if I pop back to the master by clicking back button or swiping back, they don't come back. After popping back, even the "master's" title and bar buttons are gone. I have no clue how to troubleshoot this as there are no errors.
IN my code, I am not hiding the navigation bar anywhere nor doing anything fancy with the navigation controller.
Screenshots from view hierarchy insprector:
Notice how the title and my right bar buttons on behind a few other views. the back button is at the very front. This shows that the buttons and title are not hidden, they are being covered by 3 extra views: UIVisualEffectView, _UIVisualEffectBackdropView and _UIVIsualEffectFilterView
Also in the video, you will notice that if i do a half swipe back, then cancel the swipe, the bar buttons come back. But the title doesn't.
After returning to the master, notice the master's nav bar stuff is overlaid with 2 other private class views:
I push to detail programmatically:
Relevant code:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
PlaylistDetailViewController *pdvc = (PlaylistDetailViewController*)[self.storyboard instantiateViewControllerWithIdentifier:#"PlaylistDetailViewController"];
pdvc.indexPath=indexPath;
[self.navigationController pushViewController:pdvc animated:YES];
}
I ran into this problem too, and all the solutions suggested so far are either:
too complicated
doesn't work
In the end I found out that this was caused because of the updated draw cycle for UINavigationBar in iOS10.
To get around this I had to fix it with:
self.navigationController.navigationBarHidden = YES;
self.navigationController.navigationBarHidden = NO;
It's basically triggering the navigationbar to redraw.
It's still annoying how they can just push out a new version of OS that breaks something this significant.
I ran into this same issue but it was caused from using a custom UINavigationBar that was adding a blur view. It looks like something has changed with iOS10 that when adding a title or buttons to the navigation bar they are being added at a specific index instead of being appended to the subview stack.
I was able to overcome this issue by overriding the method insertSubview:atIndex and making sure the blurView was always inserted at the back of the subview stack.
I was getting the same issue like u facing now. There are some changes i did in my code and its working. In my viewWillAppear write a code of navigation in dispatch_async
dispatch_async(dispatch_get_main_queue(), ^{
//BACK BUTTON CALLING
//NAVIGATION TITLE
});
[super viewWillAppear:animated];
This will help you to set your title and back button with the help of main queue.
actually, i just figured out a minute ago. I am using a custom GKFadeNavigationController from github.com/gklka/GKFadeNavigationController AFter removing it, that fixes the issue.
Same problem applies if you are using the LTNavigationBar library (https://github.com/ltebean/LTNavigationBar)
The workaround for me was to change the code in UINavigationBar+Awesome.m:
Replace
[[self.subviews firstObject] insertSubview:self.overlay atIndex:0];
with
[[self.subviews firstObject] insertSubview:self.overlay atIndex:self.subviews.count -1];
Swift 3.0 workaround for this:
Subclass UINavigationBar and override insertSubview(_ view: UIView, at index: Int)
override func insertSubview(_ view: UIView, at index: Int) {
if let _ = view as? UIVisualEffectView {
super.insertSubview(view, at: 0)
} else {
super.insertSubview(view, at: self.subviews.count - 1)
}
}
I found a solituion for my work. Create a view (viewBackground) with all the images and colors that conform the navigation bar and then y convert it in a image and use it like a background.
UIGraphicsBeginImageContextWithOptions(viewBackground.bounds.size, viewBackground.opaque, 0.0);
[viewBackground.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[[UINavigationBar appearance] setBackgroundImage:img forBarMetrics:UIBarMetricsDefault];
[self.navigationController.navigationBar setBackgroundImage:img forBarMetrics:UIBarMetricsDefault];

UISearchbar vanishes when in UIScrollView

I seem to be having an issue with the UISearchbar in iOS 7 vanishing in two scenarios. First the controller is fairly simple it has a nib which contains a scrollview which has in it the uisearch bar and some content. The ui search bar is at the top of the scrollview. So when I scroll the scrollview so the uisearchbar is longer visible and I exit and reneter the controller the uisearch bar is longer visible. Clicking the region makes it appear again. The uisearchbar also vanishes when I double tap it quickly. This controller worked fine is iOS 6 these issues are only happening now that I am building for ios 7
Edit
Investigating the double tap issue causing the uisearchbar to disappear. It seems that the uisearch bar when double tapped quickly is removing the uisearchbar from the view hierarchy when displaying it but never readding it back when it has been dismissed. So I can workaround that by doing
- (void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller
{
// workaround for bug in ios 7 were quickly double tapping uisearchbar (e.g it appears and get dismissed quickly)
// does not re add the uisearch bar to the correct view.
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7.0")) {
UIView *parentView = [self.scrollView.subviews objectAtIndex:0];
[parentView addSubview:self.searchDisplayController.searchBar];
}
return;
}
Have you tried doing some UI refresh stuff?
Like:
- (void)viewWillAppear:(BOOL)animated{
[self.scrollView setNeedsLayout];
}

How can I show a back arrow in the master-view popover button for UISplitViewController in iOS 7?

In my detail VC, I am implementing this UISplitViewController delegate method:
- (void)splitViewController:(UISplitViewController*)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem*)barButtonItem forPopoverController:(UIPopoverController*)pc
It is then easy for me to set the title of the button, but the result is just a button with plain text, and no back arrow. I am looking to get something like the Mail app where the master popover button also has the back chevron.
How can I do this?
Create your custom bar button item, with the chevron image, set up as you want, and set the target and action of your bar button item to be that of the one passed by the delegate callback. This way, your bar button will perform the same action as the one the system passes to you. You must create your own bar button with an image, because there is no possible way with AppStore approved API to create back bar buttons.
In iOS7, the private subclasses are UINavigationItemView + _UINavigationBarBackIndicatorView. One is the button, the other - the chevron. _UINavigationBarBackIndicatorView is a subclass of UIImageView. So it's pretty close to what you will achieve.
In iOS 8, UISplitViewController has a method:
- (UIBarButtonItem *)displayModeButtonItem
If you set the returned bar button item as the left button of a navigation bar (UINavigationBar), it will display the chevron for you.
On the other hand, if you put the returned bar button item into a toolbar (UIToolbar), it will not display the chevron.
For places where I want the chevron back button shown, but also need several of my own bar button items shown (like the Mail app on iPad does), I have to use a UINavigationBar and a UIToolbar. It's an ugly solution, but I have to partially overlay the UINavigationBar on top of the UIToolbar in order to get a back button chevron along with several of my own bar button items.
To access the default back button image used by Apple as what Leo said, the arrow is a class of type _UINavigationBarBackIndicatorView. Set this image to a back bar button and you are good to go.
Here follows the hack,
UIImage *imgViewBack ;
for (UIView *view in self.navigationController.navigationBar.subviews) {
// The arrow is a class of type _UINavigationBarBackIndicatorView. This is not any of the private methods, so I think
// this is fine for the AppStore...
if ([NSStringFromClass([view class]) isEqualToString:#"_UINavigationBarBackIndicatorView"]) {
// Set the image from the Default BackBtn Imageview
UIImageView *imgView = (UIImageView *) view;
if(imgView){
imgViewBack = imgView.image ;
}
}
}
This is based on Ryan Henning's answer.
It's possible to show a back button representing the master view from the detail view controller. The UISplitview controller doesn't provide a native method for this, but it returns a bar button object which we can directly assign as navigation controller bar button. Its obvious that the detail view controller should be inside a navigation controller for this to work.
self.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem;

Resources