I have 3 pages
Page 1: Menu
Page 2: Menu > Navigation Controller > Map listview
Page 3: Menu > Navigation Controller > Map
It's possible to switch between page 2 and 3 but when you click "Back" it always goes to page 1 and I did this using a custom back button.
After having used the custom back button once the following problem appears:
When I go to page 2 or 3 from the Menu page (Page 1) the navigation title appears and in less than a second it disappears. How is this possible?
These are the functions I am using:
private func hideAndAddNewBackButton(){
if backToRoot{
self.navigationItem.hidesBackButton = true
let newBackButton = UIBarButtonItem(title: "Back", style: UIBarButtonItemStyle.Plain, target: self, action: "back:")
self.navigationItem.leftBarButtonItem = newBackButton;
self.title = "Locaties"
}
}
func back(sender: UIBarButtonItem) {
if let viewController2 = storyboard!.instantiateViewControllerWithIdentifier("ViewController2") as? ViewController2{
self.navigationController?.pushViewController(viewController2, animated: true);
}
}
func needBackToRoot(){
backToRoot = true;
}
And this is in my viewDidLoad():
var backToRoot:Bool = false;
override func viewDidLoad() {
super.viewDidLoad()
self.hideAndAddNewBackButton();
}
My switch button:
#IBAction func showLijst(sender: AnyObject) {
if let viewController3 = storyboard!.instantiateViewControllerWithIdentifier("Lijst") as? KaartListview{
viewController3.needBackToRoot();
self.navigationController?.pushViewController(viewController3, animated: true);
}
}
In my case problem was creating custom back button and setting in pushed controller
self.navigationController?.navigationBar.topItem?.title = ""
My solutions is :
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.isNavigationBarHidden = false
self.navigationController?.navigationBar.topItem?.title = "SomeTitle"
}
I had a similar issue before and I fixed by using:
navigationController?.navigationBarHidden = false
In the viewDidLoad() function
Like this:
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBarHidden = false
}
Related
I'm fairly new to using Swift and this is my first time using Eureka to create forms. I'm having trouble figuring out how to add a "Done" button on the top of the screen to return the user back to the main view from the form view.
I've tried using
self.navigationItem.backBarButtonItem?.title = "Done"
and a couple of other solutions I've found on the internet with no luck.
class EntryFormViewController: FormViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.title = "New Entry"
self.navigationItem.hidesBackButton = false
self.navigationItem.backBarButtonItem?.title = "Done"
self.navigationItem.backBarButtonItem?.tintColor = .red
// Form
}
}
There is no navigation bar at all with this code, no back button, no title.
Thank you for your help.
Edit:
Here's some code of where I'm using the Form.
#objc func insert() {
items.append("Item \(items.count + 1)")
let insertionIndexPath = NSIndexPath(row: items.count - 1, section: 0)
tableView.insertRows(at: [insertionIndexPath as IndexPath], with: .automatic)
let nextViewController = EntryFormViewController()
self.present(nextViewController, animated: true, completion: nil)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.isNavigationBarHidden = false
}
add this code your navigationbar might be hidden and I hope your problem will be solved
I have using EKEventViewController in our app.
Code should like below
class MyEkEventViewController: EKEventViewController {
override func viewDidLoad() {
super.viewDidLoad()
let cancelButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.cancel, target: self, action: #selector(MyEkEventViewController.cancel))
self.navigationController?.navigationItem.setLeftBarButton(cancelButton, animated: false)
//self.navigationController?.navigationItem.leftBarButtonItem = cancelButton
}
}
#objc fileprivate func cancel() {
_ = navigationController?.popViewController(animated: true)
}
}
# My invocation
.
.
.
let eventViewController = MyEkEventViewController()
eventViewController.delegate = self
eventViewController.allowsEditing = true
eventViewController.allowsCalendarPreview = true
eventViewController.hidesBottomBarWhenPushed = true
eventViewController.event = event
self.navigationController?.pushViewController(eventViewController, animated: true)
Back arrow only displayed. But Cancel button is not displayed in left side navigation bar.
I have a NavigationBar at the top of a TableView. It looks nice opening/closing the search.
However, if I click on a button in a cell and get directed to another page (with segue); and then use Back button to unwind, it seems like bugged.
()
So it looks like it is pressed and opened but it shouldn't have. It should be looked like the top picture instead (just UIBarButtonItem - search button)
I couldn't figure out the issue creating this problem.
Please note that < Back is created automatically and I didn't write any code to create it. Is there something I am doing wrong?
Update: Added some snippets...
First, created a different class for handling the search
class SearchBarViewController: UIViewController, UISearchBarDelegate {
var searchBar : UISearchBar?
var searchBarWrapper : UIView?
var searchBarButtonItem : UIBarButtonItem?
func constructSearchBar()
{
searchBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Search, target: self, action: "showSearchBar")
self.navigationItem.rightBarButtonItem = searchBarButtonItem
}
func showSearchBar() {
// styling & configuration
}
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
UIView.animateWithDuration(0.2, animations: {
self.searchBar?.resignFirstResponder()
self.searchBarWrapper?.alpha = 0
}, completion: { (success) -> Void in
self.searchBar = nil
self.searchBarWrapper = nil
self.navigationItem.rightBarButtonItem = self.searchBarButtonItem
})
}
}
And my ViewController:
class ViewController: SearchBarViewController {
override func viewDidLoad() {
super.viewDidLoad()
constructSearchBar()
}
}
Regarding to emrys57's answer, I tried adding viewWillAppear() in my ViewController but I couldn't make it work, as my cancel looks a little different:
override func viewWillAppear(animated: Bool) {
super.viewDidAppear(animated)
// Here, I couldn't figure out what to put because
// my searchBarCancelButtonClicked() needs searchBar and
// forces me to use (!) but then it says, it's optional..
}
The answer is...
override func viewWillAppear(animated: Bool) {
super.viewDidAppear(animated)
navigationItem.titleView = nil
constructSearchBar()
}
You have not posted code, so it's not entirely clear what's gone wrong. Using UISearchBar, I think you must be handling the buttons separately yourself, as opposed to using UISearchController. I think that you may not be clearing away the search bar when coming back from the second VC. This code clears out the search bar in viewWillAppear:
class ViewController: UIViewController {
var cancelButton: UIBarButtonItem?
var searchButton: UIBarButtonItem?
override func viewDidLoad() {
super.viewDidLoad()
cancelButton = UIBarButtonItem(barButtonSystemItem: .Cancel, target: self, action: Selector("searchCancelPressed:"))
searchButton = UIBarButtonItem(barButtonSystemItem: .Search, target: self, action: Selector("searchPressed:"))
}
override func viewWillAppear(animated: Bool) {
super.viewDidAppear(animated)
searchCancelPressed(nil)
}
func searchPressed(sender: AnyObject) {
navigationItem.titleView = UISearchBar()
navigationItem.rightBarButtonItem = cancelButton
}
func searchCancelPressed(sender: AnyObject?) {
navigationItem.titleView = nil
navigationItem.rightBarButtonItem = searchButton
}
}
and that is working nicely for me when I do a push from a button to the second VC and then hit back.
Following the edit to the original question, this code seems to work, although it may not be the most elegant way of constructing the answer:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
navigationItem.titleView = nil
searchBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Search, target: self, action: "showSearchBar")
navigationItem.rightBarButtonItem = searchBarButtonItem
}
The function constructSearchBar no longer needs to be called in viewDidLoad, and can be deleted.
I want to have a back button on the second view controller I have. When it loads now, it does show the back button but I want to change the title from Back to something else. I implemented to viewWillAppear method where I invoke showing the navigation bar.
The following didn't work:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated);
self.navigationController?.navigationBar.hidden = false
self.navigationController?.navigationBar.backItem?.title = "Something Else"
}
Please help me change the title. Should it be in the willAppear or viewDidLoad?
Add this right before the push or popViewController statement in your first view:
let backButton = UIBarButtonItem(title: "Something Else",style: UIBarButtonItemStyle.Plain ,target: nil,action: nil)
self.navigationController!.navigationBar.topItem!.backBarButtonItem = backButton
Or you can do it in your second view this way:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated);
let backButton = UIBarButtonItem(title: "Something Else",style: UIBarButtonItemStyle.Plain ,target: nil,action: nil)
self.navigationController!.navigationBar.topItem!.backBarButtonItem = backButton
}
Ksa_coder I have tried the solution for your question and finally I got.You want to add the below coding in second view controller in viewWillAppear method
override func viewWillAppear(animated: Bool)
{
super.viewWillAppear(animated);
var btnBack = UIBarButtonItem(title: "Something Else",style: UIBarButtonItemStyle.Plain ,target: nil,action: nil)
self.navigationController!.navigationBar.topItem!.backBarButtonItem = btnBack
}
So I have a button in [2] and it pushes to [3] through the Navigation Controller so I can go back to [2] with the "Back" button in the toolbar. This all works fine.
In [4] I have a button too and I want it to go to [3]. But it should also go through the navigation controller so that when I press "Back" I can return to [2] again.
So actually I want the button on [4] to go like [ 1 ][ 2 ][ 3 ] so that I can return to [2] from [3]
#IBAction func showKaart(sender: AnyObject) {
performSegueWithIdentifier("menuToKaart", sender: sender)
}
If I understand your question, I believe try it.
Mind your root view controller is vc[2], ok?
You push from vc[2] > vc[3], next press back and return to vc[2], that's ok!
You push from vc[4] > vc[3], next press back and return to vc[4], but you need back to vc[2]?
For this logic you can create your custom behavior to vc[3]
For your vc[3] I do this to control behavior.
class ViewController3:UIViewController{
var backToRoot:Bool = false;
override func viewDidLoad() {
super.viewDidLoad();
self.hideAndAddNewBackButton();
}
private func hideAndAddNewBackButton(){
self.navigationItem.hidesBackButton = true
let newBackButton = UIBarButtonItem(title: "Back", style: UIBarButtonItemStyle.Plain, target: self, action: "back:")
self.navigationItem.leftBarButtonItem = newBackButton;
}
func back(sender: UIBarButtonItem) {
if backToRoot{
self.navigationController?.popToRootViewControllerAnimated(true);
}else{
self.navigationController?.popViewControllerAnimated(true)
}
}
func needBackToRoot(){
backToRoot = true;
}
}
Now in vc[4] I think you can modify the back button behavior of your vc[3]
I mind two way to do with your vc[4]
First using performSegue.
class ViewController4PerfomSegue:UIViewController{
#IBAction func pressButtonToPushViewController3(sender:AnyObject?){
self.performSegueWithIdentifier("showViewController3", sender: nil);
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let viewController3 = segue.destinationViewController as? ViewController3{
viewController3.needBackToRoot();
}
}
}
Second with push manual in your navigation view controller
class ViewController4Push:UIViewController{
#IBAction func pressButtonToPushViewController3(sender:AnyObject?){
let viewController3 = ViewController3(nibName: "ViewController3", bundle: nil);
viewController3.needBackToRoot();
self.navigationController?.pushViewController(viewController3, animated: true);
}
}
Edit: new way to instantiate from storyboard
class ViewController4Push:UIViewController{
#IBAction func pressButtonToPushViewController3(sender:AnyObject?){
if let viewController3 = storyboard!.instantiateViewControllerWithIdentifier("ViewController3") as? ViewController3{
viewController3.needBackToRoot();
self.navigationController?.pushViewController(viewController3, animated: true);
}
}
}
Edit: removing when new view was presented
class ViewController4Push:UIViewController, UINavigationControllerDelegate{
#IBAction func pressButtonToPushViewController3(sender:AnyObject?){
if let viewController3 = storyboard!.instantiateViewControllerWithIdentifier("ViewController3") as? ViewController3{
viewController3.needBackToRoot();
self.navigationController?.delegate = self;
self.navigationController?.pushViewController(viewController3, animated: true);
}
}
func navigationController(navigationController: UINavigationController, didShowViewController viewController: UIViewController, animated: Bool) {
self.navigationController?.delegate = nil;
self.dismissViewControllerAnimated(false, completion: nil);
//or self.removeFromParentViewController();
}
}
I hope help you, if I understand the problem
Edit: after talk in chat with Sinan we resolve it with simple way, just force back present the root element of application
class ViewCustomController:UIViewController{
override func viewDidLoad() {
super.viewDidLoad();
self.hideAndAddNewBackButton();
}
private func hideAndAddNewBackButton(){
self.navigationItem.hidesBackButton = true
let newBackButton = UIBarButtonItem(title: "Back", style: UIBarButtonItemStyle.Plain, target: self, action: "back:")
self.navigationItem.leftBarButtonItem = newBackButton;
}
func back(sender: UIBarButtonItem) {
if let viewControllerRoot = storyboard!.instantiateViewControllerWithIdentifier("ViewControllerRoot") as? ViewControllerRoot{
self.navigationController?.pushViewController(viewController2, animated: true);
}
}
}
[4] needs to be embedded in a navigation controller. After that, change you #IBAction to use pushViewController:Animated: on the navigationController instead of performSegueWithIdentifier