Issue: Upon displaying the second view, the Back button shows and then quickly disappears.
I'd like the Back button to persist on the second view.
Setup:
2 views.
The button that opens the second view is done via a "Show" segue.
SecondVC:
override func viewDidAppear(_ animated: Bool) {
let controller = TipJarViewController<TipJarOptions>()
self.present(controller, animated: false, completion: nil)
}
It seems to happen because of how I'm doing the viewDidAppear. It seems that I'm replacing the entire view with the self.present. I'm not sure what to search for or modify so it can still show the Back button.
Bonus question: Wondering if I'm placing this code in the wrong section. On the transition to the second view the screen is blank for a bit and then will show the view's contents. This doesn't seem like an optimal user experience. Open to any suggestions here.
After moving present to first VC via Frankenstein's suggestion
You don't need to segue into the second controller and then present. Instead, present directly instead of show the controller keeping it as rootViewController of a UINavigationController. Do this on the action:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let controller = UINavigationController(rootViewController:
TipJarViewController<TipJarOptions>())
present(controller, animated: false, completion: nil)
}
Edit: To add back button in TipJarViewController, here is the code:
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Back", style: .plain, target: self, action: #selector(handleBack))
}
#objc func handleBack() {
dismiss(animated: true)
}
Related
I was having this issue and I've tried a lot of solutions that was proposed by some kind people here in the following topic:
Swift - How to hide back button in navigation item
I created a ViewController class:
import SwiftUI
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.setHidesBackButton(true, animated: true)
self.navigationController?.navigationBar.isHidden = true
//self.navigationItem.backButtonTitle = "hohoho"
self.navigationItem.leftBarButtonItem = nil
self.navigationItem.hidesBackButton = true
//UINavigationBar.appearance().isHidden = true
//navigationItem.backBarButtonItem = UIBarButtonItem(title: "Home/Return or nohing", style: .bordered, target: nil, action: nil)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationItem.setHidesBackButton(true, animated: true)
self.navigationController?.navigationBar.isHidden = true
//self.navigationItem.backButtonTitle = "hohoho"
self.navigationItem.leftBarButtonItem = nil
self.navigationItem.hidesBackButton = true
//UINavigationBar.appearance().isHidden = true
//navigationItem.backBarButtonItem = UIBarButtonItem(title: "Home/Return or nohing", style: .bordered, target: nil, action: nil)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.navigationItem.setHidesBackButton(true, animated: true)
self.navigationController?.navigationBar.isHidden = true
//self.navigationItem.backButtonTitle = "hohoho"
self.navigationItem.leftBarButtonItem = nil
self.navigationItem.hidesBackButton = true
//UINavigationBar.appearance().isHidden = true
//navigationItem.backBarButtonItem = UIBarButtonItem(title: "Home/Return or nohing", style: .bordered, target: nil, action: nil)
}
}
and AS you can see in the above code I tried every single way with no change - back button still appear - then I try to make simple change like change the text of the back button or the shape and also there is no result!!
Am I do something wrong :( Because I feel like the whole class is not active for my view
Do I need to create an object of ViewController or something like that? Because I just wrote the mentioned code about my view code.
MY GOAL: I just want to move from view to another with no back button if there is another way I wouldn't mind to do it.
PPLLLSSSS HELPP ME Guys I'm so tired, I'll work on another things until find a solution for that and I'm sure there is a lot of people who want a solution for that issue.
Once I find the solution I'll share it with you guys :) Best Wishes and Regards
You just have to add the below code in the ViewController where you want to hide the backbutton.
navigationItem.setHidesBackButton(true, animated: true)
Segue from viewController to viewController2 and name the segue testSegue. This should work.
I had the exact same problem and the only solution that worked was adding
.navigationBarBackButtonHidden(true) in my SwiftUI view
I have a tab bar view. In that, one of three tabs is a contacts app. In that contacts app, there are three pages, one to display all the contacts, second to display one particular contact selected in the first VC, and third is to add a new contact. (Pretty much similar to the built-in iOS app) How can I create a fluent flow between these three pages. (Do not forget they should be inside one tabbar)
I've added all the required buttons.
First Page - Display all contacts
Second Page - Show one particular contact
Third Page - Add new contact
I've embedded 3 navigation view controller (one to each of the 3 pages)
First page has 'add' button that should lead to third page.
Second page has two buttons, one to go back to first and the other to go to third.
Third has two buttons, one each to go the each of the other two pages.
I've created these buttons programmatically inside the navigation bar using this function -
override func viewDidAppear(_ animated: Bool) {
navigationItem.title = "Add New Contact"
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Done", style: UIBarButtonItem.Style.plain, target: self, action: #selector(theTransition))
}
#objc func theTransition() {
let second = self.storyboard?.instantiateViewController(withIdentifier: "OneNavID") as! OneNavigationViewController
self.present(second, animated: true, completion: nil)
}
(The above code is an example of going from page 3 to 1)
These buttons are working properly, but they show a new page which is out of the tab bar controller.
I want them to stay inside the tab view. Kindly help! Do ask if you have any doubt in the question. I've tried best to explain it in simple and short words.
I've looked on the internet a lot, but I couldn't find any instance where each of three view controllers have one navigation controller each (which I assume is needed since each of them has incoming and outgoing links to/from other pages).
Second Page -
override func viewDidAppear(_ animated: Bool) {
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Edit", style: UIBarButtonItem.Style.plain, target: self, action: #selector(theTransition))
}
#objc func theTransition() {
let second = self.storyboard?.instantiateViewController(withIdentifier: "ThreeNavID") as! ThreeNavigationViewController
self.present(second, animated: true, completion: nil)
}
Third Page -
override func viewDidAppear(_ animated: Bool) {
navigationItem.title = "Add New Contact"
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Done", style: UIBarButtonItem.Style.plain, target: self, action: #selector(theTransition))
}
#objc func theTransition() {
let second = self.storyboard?.instantiateViewController(withIdentifier: "NavID") as! NavigationViewController
self.present(second, animated: true, completion: nil)
}
Don't use 3 navigation controllers. Use one navigation controller like this
UITabBarController_____ Another View Controller1
|
|____ Another View Controller2
|
|____ Contact - UINavigationController -- FirstPage
UINavigationController -- FirstPage --> SecondPage --> ThirdPage
Embed the first Page in the navigation controller and push second and third pages. Don't create a new instance for the first page. Use popViewController to go to the previous view controller.
You can pass data to the next view controller with pushViewController and use custom delegate or closure to send data to the previous view controller. Or create a variable in custom navigation controller class like this
class CustomNavigationController: UINavigationController {
var name: String?
}
Then read and write data from other view controllers like this
class FirstPage: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
print((self.navigationController as? CustomNavigationController)?.name)
(self.navigationController as? CustomNavigationController)?.name = "FirstPage"
}
#objc func goToSecondPage() {
if let secondPage = self.storyboard?.instantiateViewController(withIdentifier: "SecondPage") as? SecondPage {
self.navigationController?.pushViewController(secondPage, animated: true)
}
}
#objc func goToThirdPage() {
if let thirdPage = self.storyboard?.instantiateViewController(withIdentifier: "ThirdPage") as? ThirdPage {
self.navigationController?.pushViewController(thirdPage, animated: true)
}
}
}
class SecondPage: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
print((self.navigationController as? CustomNavigationController)?.name)
(self.navigationController as? CustomNavigationController)?.name = "SecondPage"
}
#objc func goToThirdPage() {
if let thirdPage = self.storyboard?.instantiateViewController(withIdentifier: "ThirdPage") as? ThirdPage {
self.navigationController?.pushViewController(thirdPage, animated: true)
}
}
#objc func goToFirstPage() {
self.navigationController?.popViewController(animated: true)
}
}
class ThirdPage: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
print((self.navigationController as? CustomNavigationController)?.name)
(self.navigationController as? CustomNavigationController)?.name = "ThirdPage"
}
#objc func goToFirstPage() {
self.navigationController?.popToRootViewController(animated: true)
}
#objc func goToSecondPage() {
self.navigationController?.popViewController(animated: true)
}
}
I've a NavigationViewController which segues to a TabbedBarController. I don't want to show the back button on the TabbedBarController.
I've tried both these code snippets in Swift , neither works,
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tabBarController?.navigationItem.hidesBackButton = true
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationItem.hidesBackButton = true
}
Here's a snap shot,
Here's the tabbed bar view controller,
How can I hide the back button on the Tabbed bar view controller. How can I hide the back button on my tabbed bar controller?
There are quite many ways to do what you want, but what I'm 99.9% sure that would work is that you can add a barButton in your leftBarButtonItems to replace the default backButton of your navigationController:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationItem.leftBarButtonItems = [UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)]
}
Also, when overriding any lifecycle methods of a controller, you might not want to miss anything from the parent class, so don't forget to call its super equivalent like super.viewWillAppear(animated)
I hope this helps!
EDIT: Two ways to do what you want in tabBarController and since I can already picture the flow of your project.
Put the code inside the viewWillAppear of your tabBarController. This means that you might need to subclass the UITabBarController. So it should be like this:
class MyTabBarController: UITabBarController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationItem.leftBarButtonItems = [UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)]
}
}
You should present modally your tabBarController (this is more ideal).
I built a simple 'About' page for my app that is simply a webView with local HTML. My Settings are contained within a separate storyboard and the AboutViewController is a view within that storyboard.
When the AboutViewController is presented it no longer shows a back button to go back to the settings.
This has worked perfectly fine for the past two weeks and has suddenly stopped working today. Is there a better way to push the view onto the navigation controller?
let storyboard = UIStoryboard(name: "Settings", bundle: nil)
let aboutViewController = storyboard.instantiateViewControllerWithIdentifier("AboutViewController") as! AboutViewController
self.navigationController?.pushViewController(aboutViewController, animated: true)
self.tableView.deselectRowAtIndexPath(indexPath, animated: true)
I have a slightly older version of my app running on my phone and it looks like this:
And now it looks like this:
Well a workaround is to put it back yourself.
override func viewWillAppear(animated: Bool)
{
super.viewWillAppear(animated)
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "< Back", style: UIBarButtonItemStyle.Plain, target: self, action: "back")
}
func back()
{
navigationController?.popViewControllerAnimated(true)
}
Here's what's going on:
I have a Navigation Controller with A-TableViewController set as root view controller. Once I click on a cell in A, it'll take me to B-ViewController. The navigation controller has an identifier "MessagesViewController". Here's my code thus far in A-TableViewController:
func tableView (tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let sb = UIStoryboard(name: "Main", bundle: nil)
let messagesVC = sb.instantiateViewControllerWithIdentifier("MessagesViewController") as! MessagesViewController
//Some code here
//This has a back button, but nothing else
self.navigationController?.pushViewController(messagesVC, animated: true)
//This has no back button, but everything else that I intended works
self.navigationController?.presentViewController(messagesVC, animated: true, completion: nil)
I want to be able to go back to A-TableViewController with everything working. Is it the way I'm pushing/presenting the view controller that's messing it up? Anyone have any clue why I've been stuck on this for the past 3 days?
You get built in back button when you push a view on to a navigation view. The presentViewController is modally displaying your view. What I've done in the past is add my own back button to the view and present it. Then when you press it you call dismissViewController.
After Presenting your B-ViewController Try this in viewDidLoad:
let btnBack = UIBarButtonItem(title: "Back", style: .plain, target: self, action: #selector(dismissVC))
btnBack.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.black], for: .normal)
navigationItem.setLeftBarButton(btnBack, animated: true)
#objc func dismissVC() {
self.dismiss(animated: true, completion: nil)
}
You can use the prepareForSegue method to pass data, something like this:
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if segue.identifier == "messageSegue" {
let vc: B-ViewController = segue.destinationViewController as! B-ViewController
//then set properties of your new viewController like this
vc.property = dataToPass
}
}
If you are indeed using a navigation controller, than your problem should be quite simple.
Create an #IBAction, and in it, call popToRootViewControllerAnimated, like so:
#IBAction func rootButton(sender: UIButton) {
navigationController?.popToRootViewControllerAnimated(true) // or false :)
}