First of all: I'm using Swift 5 with Xcode 10 (iOS 12.0).
I'm pretty new to Swift/iOS development and watched a couple of videos on how to add a "back" button to the navigation bar. In all of them (with Swift 3) the button just magically appears once the app is run after adding a segue (between an item in the first scene and the second scene) and a title for both navigation bars.
My app has three ViewControllers/scenes:
Login without navigation bar ("login" button: segue to scene 2)
Table View (linked to scene 3 with segue, so I can just tap on an item in the list)
Further information for a single item in the Table View
The segue between scene 2 and 3 is set to "show (e.g. push)" because "push" is deprecated and crashes the app.
I added both navigation bars to the navigation controllers (2 & 3) by hand and want to add an arrow icon to the navigation bar of scene 3. What I've tried so far:
Add titles for the navigation bar in both scenes
Set the "Back button" attribute (Navigation bar text), which created a child object
Then set the child object's "Image" attribute
Set the "Back" and "Back Mask" attribute (Navigation bar) to the same image
Nothing shows up though, neither in Xcode nor in the simulator (not even the image).
Is it even still possible to get an automatic "back" button or do you now have to add it yourself using a "Bar Button Item"?
So when you show a View Controller such as your v2,v3 those View Controllers are no longer in the same navigation stack as your v1, that is why it is not automatically showing the back button.
I don't know why it is saying your Push function is deprecated but if you could grab a screenshot maybe I can give you a reason why. I am using Swift5 and I'm able to use this : self.navigationController?.pushViewController(vc, animated: true)
To answer your question, if you want to add a back button to v2,v3 then you DO have to use BarButtonItem, and call
self.dismiss(viewController, true) I strongly recommend you not do it this way if your intent is to have them in the same Navigation stack as your v1.
Answering my own question: Yes, it's still (Xcode 10/Swift 5) possible to make it add a "back" button automatically.
Push segues are deprecated since iOS 8, so use Show (e.g. Push) instead!
Usually a Show (e.g. Push) segue uses Show but if there's a NavigationController somewhere to the left (scenes going from left to right) of the current ViewController, it automatically uses Push, which also adds a "back" button to the NavigationBar of the next scene or, if there's no NavigationBar, it simply adds the button where the bar would usually be.
My scenes now look like this:
ViewController1: Login without NavigationBar ("login" button: segue to NavigationController)
NavigationController: With automatic segue to a new UITableViewController (if added through the library)
ViewController2: Table View (linked to 4. with segue)
ViewController3: Further information for a single item
Adding data to the segues between 1. and 3. (using 2.) is handled a little bit different than it would be without NavigationController:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let navC = segue.destination as? UINavigationController
let vc2 = navC?.viewControllers.first as! ViewController2
vc2.myinformation = myinfosArray
}
(Bad) Alternative to a NavigationController:
Add a NavigationBar and a BarButtonItem and link it to the previous view like you would any other button.
Disadvantage: The view (in my case "ViewController2") resets once you switch to the next one (because the two views aren't on the same stack, see jaelee's explanation above), so if you go back you have to set everything up again.
Related
I have being trying different things and looking around for a while without finding an answer to my problem. Maybe I'm doing something fundamentally wrong.
The sample application consists of:
A first view controller that displays a second view controller using a segue. This works fine.
A second view controller, in which I have simulated the display of a third view programmatically, which contains a bar item button (named "Done") that I would like to display.
The bar item button in the third view controller is not displayed at runtime but is displayed in IntefaceBuidler at design time.
This third view controller needs to be displayed modal.
What I'm doing wrong to display this bar item button?
A sample project illustrating the problem is available here.
Below a screen capture of the bar item button at design time:
Below a screen capture of the bar item button not showing at design time:
PS:
Please disregard the "Unknown class ThirdViewControlller in Interface Builder file.", since the ThirdViewController is displayed fine at runtime. Also, the "Done" button in the middle of the view works fine.
In SecondViewController you need to push the third onto the navigation controller stack like so:
self.navigationController?.pushViewController(thirdViewController, animated: true)
You are currently presenting it as a modal. Also, you've unnecessarily added a second UINavigationController to your storyboard (for the third view controller)
If you want to present a modal, then you'd need to embed the controller in a navigation controller:
let navController = UINavigationController(rootViewController: thirdViewController)
self.present(navController, animated: false)
If you prefer to keep this within the storyboard, then you need to provide a identifier for the UINavigationController and insatiate that in your function.
The above button is a navigation bar item that will only be displayed on the navigation bar . For achieving your desired result , you first have to embed the navigation controller at least in your second viewcontroller and then you should do a push segue rather than modal . Navigation controller can be added by
whith your second viewcontroller selected go to Editor\Embed In\Navigation Controller
for pushing the viewcontroller programatically onto user navigation controller's stack use
self.navigationController?.pushViewController(nextViewController, animated: true)
This is the current layout for my application. As you can see, I have a ViewController that is embedded in a TabBarViewController. You can see I have two tab bars in both of those bottom view controllers but only the first one shows up. In the second view controller after the push segue, the tab bar disappears. Why is this?
I added the properties for the First view controller and it is not set to hide the bottom bar during the segue so I am confused as to why it would disappear after the segue. Any ideas?
You'll need to wrap your tabBar's root viewControllers in a UINavigationController. So your UITabBarController would actually be pointed at the Navigation Controller. Then as you move around in that navigation controller, the tab bar will stay in place.
To fix this in your application, select your view controller in storyboard, then click "Editor" -> "Embed In" -> "Navigation Controller".
Here's a visual representation I just threw together for anyone else who comes across this problem. If you remove the "NavigationController" in the storyboard shown below, the tab will disappear when you click the button in "First View". With the navigation controller, you will maintain the tab bar. Hope this helps.
Try set self.tabBarController.tabBar.translucent = NO; in viewWillAppear
You could also try to dismiss the views by adding an outlet/action. For example, I experienced an issue where I had a TabBar view controller and needed to segue between 2 different views (ImageViews) on one of the tabs and as soon as I did a traditional segue, the whole tab bar disappeared. I had created the following "Back button" to clear the view:
#IBAction func backBtnPressed(_ sender: AnyObject) {
dismiss(animated: true, completion: nil)
}
Note: It is an important practice to clear views out as they will stack up overtime and will reduce the performance of your app.
Technical Info:
https://developer.apple.com/reference/uikit/uiviewcontroller/1621505-dismiss
Not sure if this helps but worth mentioning!
I have been searching for a solution for 6 hours, and come up with nothing that applies to my situation. my storyboard follows the flow of:
TabBarViewController -> NavigationController ->TableViewController -> UIViewController (see picture below)
When the "Notify" button, in the last view controller (Stranger view controller), is clicked, I want to programmatically transition/segue from that View Controller(Stranger View Controller), to a different child of the TabBarViewController (it is the controller titled "Look Around" within the illustration).
Every time I perform a traditional segue:
option + drag segue from Stranger View Controller --> Look Around
View controller
Give segue an identifier
programmatically use self.performSegueWithIdentifier.
I get a transition. but the "Look Around" tab bar is gone in the storyboard, and in the simulator, once I hit "Notify", the view changes to the "look around" view, but the tab bar below does not reflect that change, as it still has the previous tab highlighted.
I have already handled all the other processing within the IBAction function that I need to handle. It is just a matter of, correctly, sending the user to a different view, once they have hit "Notify".
Any guidance on this would be greatly appreciated.
If you have any questions or concerns for me, please do not hesitate to ask. I am new at this, and am open to any help.
ViewController is a child of NavigationBar and NavigationBarController is a Child of TabBarController. So Segue is not required as it will disturb the flow.
Try programmatically
#IBAction func notifyButtonTapped(sender: AnyObject) {
tabBarController?.selectedIndex = 1
tabBarController?.tabBar.hidden = false
self.navigationController?.popToRootViewControllerAnimated(false)
}
For my project UIPageViewController could be a good choice, so, I started with the template provided by XCode 6.4 starting new project. I used the template: Page-Based Application which has already the basic implementation of UIPageViewController. The opportunity to scroll the pages is working fine, however, I would like to add the navigation bar as well. After reading the articles on that topic I tried to embed DataViewController into NavigationController (Editor>Embed), and then added the Navigation Bar Button using the storyboard from Interface Builder. However, I cannot see that button when I compile the app. Moreover, it looks that the back navigation works for the pages when you press on the spot where Navigation Bar Button should be located, but button is not visible. Later I found out that the back navigation works not only on that spot but on all left margin of the view. It seems like a bug.
1. How to make Navigation Bar Back Button visible?
2. How to remove that buggy behavior when navigation reacts to the press of all the margin instead of just location of the button?
If you want to have the navigation controller show up, you need to change:
let startingViewController: DataViewController = self.modelController.viewControllerAtIndex(0, storyboard: self.storyboard!)!
so that startingViewController is the navigation controller your dataViewController is embedded in. You can do this by changing the storyboard ID of the navigation controller and saying something like:
let startingViewController: UIViewController = (self.storyboard?.instantiateViewControllerWithIdentifier("NavController"))!
However this is going to break the template as the rest of the code thinks the starting view controller is a DataViewController, so you will need to change that.
The "buggy behavior" is the standard page controller navigation mechanism when the transitionStyle is set to UIPageViewControllerTransitionStylePageCurl.
There are 2 View Controllers in my storyboard, VC_A and VC_B
I have embeded a navigation controller in VC_A which is a Table View Controller, I then control drag the Prototype Cell into VC_B to create a segue. If I select "show" in "selection segue" then in VC_B I can see the outline of the navigation bar but I am unable to select it or add any bar buttons to it, it also doesn't appear in the hierarchical view.
However if I select the "push (deprecated)" option when choosing the type of segue, I am able to select the navigation bar in VC_B and add buttons to it, it also show up in the hierarchical view as a Navigation Item.
The only work around I can find is to choose show, then change the segue to push(deprecated) in the Attribute Inspector so the Navigation Item will show up in the hierarchical view, then change the segue back to show. But I am worry that this might cause problems further down the line.
Is there a way to add a Bar Button to VC_B's navigation bar without using the work around?
Just drag the "Navigation Item" from object library to the navigation bar and it should work as expected. You can make changes as you like and it works exactly like in Xcode 5.
Interestingly, when you first time made the connection b/w your table view controller and view controller using Push you can start editing the navigation bar without a problem (e.g put bar items onto it).
Then delete the connection between your table view controller and view controller (but do not delete the nav bar items you just added), then re-connect the two controllers by using segue Show, you will see the navigation bar works just like segue Push now.
Hope it helps
I think the way you do it (going through the deprecated push) is not wrong even though there's another way. In fact, when you turn the Segue into a push, you get a Navigation Item out of it.
So all you have to do is add a Navigation Item to your View Controller and that'll do the trick:
This seems Xcode bugs.
In my case, i am re-create segue by this sequence:
Delete existing seque. (I am using "Action segue - Show")
Drag new segue with "Non-Adaptive Action Segue - Push (deprecated)"
Delete segue no.2
Re-create/connect "Action Seque - Show". (No.1)
Done
Now, i can edit navigation title and add custom navigation item button as usually.
I am using Xcode 6.4, and minimal target iOS version 7.
In your viewController :
self.navigationItem.title = "Second VC"
self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Play, target: self, action: "playFunction:")