set navigation backBarButtonItem to go to specific UIViewController in Swift - swift

I need the navigation's back button always pops a specific UIViewController.
override func viewDidLoad() {
super.viewDidLoad()
//set title image
var logoImage:UIImage = UIImage(named: "barra")!
var logoImageView : UIImageView = UIImageView(image: logoImage)
logoImageView.frame = CGRectMake(0, 0, 320, 44)
logoImageView.contentMode = .ScaleAspectFit
logoImageView.contentMode = UIViewContentMode.Center
logoImageView.clipsToBounds = true
self.navigationItem.titleView = logoImageView
//set back image
var backImage:UIImage = UIImage(named: "freccia")!
backImage = backImage.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal)
self.navigationItem.backBarButtonItem = UIBarButtonItem(title:"", style: .Plain,target: self, action: "goToServizi:")
self.navigationController!.navigationBar.backIndicatorImage = backImage
self.navigationController!.navigationBar.backIndicatorTransitionMaskImage = backImage
//set menu image
var menuImage:UIImage = UIImage(named: "menu")!
menuImage = menuImage.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal)
self.navigationItem.rightBarButtonItem?.image = menuImage
}
func goToServizi(sender: UIBarButtonItem)
{
self.navigationController?.popToViewController(ServiziVC(), animated: true)// here I add a breakpoint, but it is never executed.
}
ServiziVC is the UIViewController that I need to show every time I click on the Back button.
I can't understand why goToServizi func is not called. Please help.
Thank you.

Here is the example for you.
import UIKit
class SecondViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//Customise your barButton Like this
var backImage:UIImage = UIImage(named: "freccia")!
backImage = backImage.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal)
var backButton = UIBarButtonItem(image: backImage, style: UIBarButtonItemStyle.Bordered, target: self, action: "goToThird")
self.navigationItem.leftBarButtonItem = backButton
}
func goToThird(){
//Initiate newViewController this way
let ThirdView = self.storyboard?.instantiateViewControllerWithIdentifier("ThirdViewController") as ThirdViewController
self.navigationController?.pushViewController(ThirdView, animated: true)
}
}
EDIT
Click on the ViewController which you want to initiate with identifier and you can find StoryBoard ID in Identity Inspector like shown in below Image.
HERE is the example for you for more reference.
Modify code as per your need.may be this will help you.

self.navigationController?.popToViewController(ServiziVC(), animated: true)You can't customize the back button action like that. This works:
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.hidesBackButton = true;
var backImage:UIImage = UIImage(named: "freccia")!
backImage = backImage.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal)
var fakeBackButton = UIBarButtonItem(image: backImage, style: UIBarButtonItemStyle.Bordered, target: self, action: "goToServizi:")
self.navigationItem.leftBarButtonItem = fakeBackButton;
}
func goToServizi(sender: UIBarButtonItem)
{
self.navigationController?.popToViewController(ServiziVC(), animated: true)
}
Alternatively, you could override the UINavigationController's delegate method as described here : UINavigationController and back button action

Related

UINavigation controller: present and dismiss programmatically

I have a TableViewController which I want to present modally and I need it to have a NavigationBar.
To get that navbar, I have an embedded UINavigationController and as far as I know, that UINavigationController is what I have to present modally, so that's what I've done.
Everything works just fine, but I can't manage to dismiss that controller properly. Here is what I've got so far:
func presentErrorMessages(errorMessages: [String]) {
let storyBoard: UIStoryboard = UIStoryboard(name: "Message", bundle: nil)
let infoMessagesNavigationViewController = storyBoard.instantiateViewController(withIdentifier: "InfoMessagesNavigation") as! ModalNavigationController
let infoMessagesTableViewController = infoMessagesNavigationViewController.viewControllers[0] as! InfoMessagesTableViewController
infoMessagesTableViewController.errorMessages = errorMessages
self.navigationController?.present(infoMessagesNavigationViewController, animated: true)
}
I use that to present ModalNavigationController, and this to dismiss it:
class ModalNavigationController: BaseNavigationController {
var backNavItem = UINavigationItem()
var okNavItem = UINavigationItem()
override func viewDidLoad() {
super.viewDidLoad()
let backButton = UIBarButtonItem(title: "Back", style: .plain, target: self, action: #selector(dismissModal))
backNavItem.leftBarButtonItem = backButton
...
var items = [UINavigationItem]()
items.append(backNavItem)
self.navigationBar.items = items
}
#objc func dismissModal() {
self.dismiss(animated: true)
}
}
When I press that back button, there is no change but the navbar which gets blank (with no title). I have the feeling that the application just 'forgets' what is the NavigationController used before the new one is presented.
How can I solve this?
Try something like this:
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Back", style: .done, target: self, action: #selector(dismissModal))
...
}
#objc func dismissModal() {
self.dismiss(animated: true, completion: nil)
}
I managed to solve the problem by placing and invoking the dismissfunction on my TableViewController rather than my NavigationController:
...
public func setBackButton(){
if self.navigationController != nil {
let item = UIBarButtonItem(title: "Back", style: .plain, target: self, action: #selector(dismissModal))
self.navigationItem.leftBarButtonItem = item
}
}
#objc func dismissModal() {
self.dismiss(animated: true)
}

UIPopoverPresentationController popover displays over the entire view

I am trying to create a rightBarButtonItem that appears throughout my app. When this barItem is clicked I want to show a modal popup using UIPopoverPresentationController. I have been able to get the button to show up on the barItem on all the views. However when i click on the button the xib takes over the entire view (including nav bar, see image below). Please see the class below:
class MyAppsNavigationController: UINavigationController, UINavigationControllerDelegate, UIPopoverPresentationControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
self.navigationBar.barTintColor = Colors.Red01.color()
self.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName : UIColor.white]
}
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
viewController.navigationItem.rightBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "Ellipsis"), style: .plain, target: self, action: #selector(displayMenu(sender:)))
}
func displayMenu(sender: UIBarButtonItem)
{
let filterVC = DropdownMenuController(nibName: "DropdownMenuController", bundle: nil)
let nav = UINavigationController(rootViewController: filterVC)
nav.modalPresentationStyle = UIModalPresentationStyle.popover
//nav.isNavigationBarHidden = true
nav.preferredContentSize = CGSize(width: 200, height: 300)
let popover = nav.popoverPresentationController! as UIPopoverPresentationController
popover.permittedArrowDirections = .up
popover.delegate = self
popover.barButtonItem = self.navigationItem.rightBarButtonItem
popover.sourceView = self.view;
var frame:CGRect = (sender.value(forKey: "view")! as AnyObject).frame
frame.origin.y = frame.origin.y+20
popover.sourceRect = frame
popover.delegate = self
self.present(nav, animated: true, completion: nil)
}
func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle {
return .none
}
}
Result when clicked on the button:
When clicked the popup takes over entire view:
Any chance you're not using the right delegate method? I think this looks better:
func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
return .none
}
Also, in this case sourceView and sourceRect is not needed: specifying a barButtonItem for the popover presentation controller is sufficient.
https://developer.apple.com/documentation/uikit/uipopoverpresentationcontroller/1622314-barbuttonitem

Swift - Call UIToolBar by buttonClick Event

In my viewController there are one button and textField. When use click on textField it fires didBeginEdit event and i can call a toolbar.
This is my view :
MyView
When user click on textField it seems like below :
textFieldClicked
And My Swift code is below :
Class ViewController: UIViewController {
#IBAction func btn(sender: AnyObject) {
// i want to call ToolBar here ...
}
#IBOutlet weak var textFieldOutlet: UITextField!
#IBAction func txtFieldBeginEdit(sender: AnyObject) {
raiseToolBar(textFieldOutlet)
}
var datePicker : UIDatePicker!
let ToolBar = UIToolbar()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
func raiseToolBar(textField : UITextField)
{
self.datePicker = UIDatePicker(frame: CGRectMake(0,0,UIScreen.mainScreen().bounds.height , UIScreen.mainScreen().bounds.height / 3))
self.datePicker.backgroundColor = UIColor.whiteColor()
self.datePicker.datePickerMode = .Date
textField.inputView = self.datePicker
ToolBar.barStyle = .Default
ToolBar.translucent = true
ToolBar.tintColor = UIColor(red : 92/255, green : 216/255 ,blue : 255/255, alpha: 1 )
ToolBar.sizeToFit()
let done = UIBarButtonItem(title: "Tamam" , style: .Plain , target: self, action: #selector(ViewController.doneClick))
let space = UIBarButtonItem(barButtonSystemItem: .FlexibleSpace, target : nil , action: nil)
let cancel = UIBarButtonItem(title: "İptal" , style: .Plain , target: self, action: #selector(ViewController.cancelClick))
ToolBar.setItems([done , space , cancel], animated: true)
ToolBar.userInteractionEnabled = true
textField.inputAccessoryView = ToolBar
}
func doneClick() {
}
func cancelClick() {
}
}
At this point there is no problem. Bu i want to call this UIToolBar by clic on the button(named btn). Under btnClick event i tried to send empty textField to raiseToolBar method but it also don't work. How can i edit my code to call ToolBar by buttonClick
**************** edit *****************
textFieldOutlet.becomeFirstResponder()
raiseToolBar(textFieldOutlet)
i solve like above. is it a clear way ?
You can assign first responder to your text field like this inside your btn action:
textFieldOutlet.isFirstResponder = true

navigation bar button text disappears

I have 2 nav bar buttons at the top of the screen, one with an image an another with text like so:
When I present a new view controller with a new nav controller/root controller and then dismiss it, going back to the same view controller, the text disappears like so:
Here's the code for the view controller
override func viewDidLoad() {
setupNavBarButtons()
}
func setupNavBarButtons() {
let searchImage = UIImage(named: "search_icon")?.imageWithRenderingMode(.AlwaysOriginal)
let searchBarButtonItem = UIBarButtonItem(image: searchImage, style: .Plain, target: self, action: #selector(handleSearch))
navigationItem.rightBarButtonItem = searchBarButtonItem
let filterBarButtonItem = UIBarButtonItem(title: "Filter", style: .Plain , target: self, action: #selector(displayFilter))
navigationItem.leftBarButtonItem = filterBarButtonItem
}
func presentAccountController() {
let accountController = AccountController()
accountController.listController = self
let vc = UINavigationController(rootViewController: accountController
presentViewController(vc, animated: true, completion: nil)
}
The controller I'm dismissing to return to the original view controller:
class AccountController: UIViewController, UITableViewDelegate, UITableViewDataSource, MFMailComposeViewControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
setupViews()
view.backgroundColor = UIColor.rgb(245, green: 245, blue: 245)
let closeButtonItem = UIBarButtonItem(title: "Close", style: .Plain, target: self, action: #selector(dismissController))
navigationItem.leftBarButtonItem = closeButtonItem
}
func dismissController() {
self.dismissViewControllerAnimated(true, completion: nil)
}
I've tried calling it in viewWillLoad, viewDidLoad, viewDidAppear. Still no change and the bug still occurs.
You can do this and create a frame with a wide width when you create the button
lazy var filterButton: UIButton = {
let button = UIButton(type: .system)
button.frame = CGRect(x: 0, y: 0, width: 60, height: 30) // Set the width here to make it wider
button.setTitle("Filter", for: .normal)
button.titleLabel?.font = UIFont.systemFont(ofSize: 18)
button.setTitleColor(UIColor.white, for: .normal)
button.addTarget(self, action: #selector(filterButtonTapped), for: .touchUpInside)
return button
}()
var leftBarButtonItem: UIBarButtonItem?
override func viewDidLoad() {
super.viewDidLoad()
leftBarButtonItem = UIBarButtonItem(customView: filterButton)
navigationItem.leftBarButtonItem = leftBarButtonItem
}
#objc func filterButtonTapped() {
print("Filter button tapped")
}

Swift custom back button in navigation bar

I am trying to use a custom image for my back button in the navigation bar. I am using the below code, which adds the image, but also keeps the text "Back" in the button. I want to also remove the text. Can I do that?
self.navigationController?.navigationBar.backIndicatorImage = UIImage(named: "icon-back")
self.navigationController?.navigationBar.backIndicatorTransitionMaskImage = UIImage(named: "icon-back")
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: UIBarButtonItemStyle.Plain, target: nil, action: nil)
Try code below :-)
func SetBackBarButtonCustom()
{
//Back buttion
let btnLeftMenu: UIButton = UIButton()
btnLeftMenu.setImage(UIImage(named: "back_arrow"), for: UIControlState())
btnLeftMenu.addTarget(self, action: #selector(UIViewController.onClcikBack), for: UIControlEvents.touchUpInside)
btnLeftMenu.frame = CGRect(x: 0, y: 0, width: 33/2, height: 27/2)
let barButton = UIBarButtonItem(customView: btnLeftMenu)
self.navigationItem.leftBarButtonItem = barButton
}
func onClcikBack()
{
_ = self.navigationController?.popViewController(animated: true)
}
If you want to add Back button in every UIViewController then you can add the code in UIViewController extension else you can use addBackButton() directly as follows.
extension UIViewController {
func addBackButton() {
let btnLeftMenu: UIButton = UIButton()
let image = UIImage(named: "backButtonImage");
btnLeftMenu.setImage(image, for: .normal)
btnLeftMenu.setTitle("Back".localized, for: .normal);
btnLeftMenu.sizeToFit()
btnLeftMenu.addTarget(self, action: #selector (backButtonClick(sender:)), for: .touchUpInside)
let barButton = UIBarButtonItem(customView: btnLeftMenu)
self.navigationItem.leftBarButtonItem = barButton
}
func backButtonClick(sender : UIButton) {
self.navigationController?.popViewController(animated: true);
}
}
Make sure you should add the following file "backButtonImage.png" in your app bundle.
Call this method self.addBackButton()in your viewDidLoad method of your custom UIViewController class like this
override func viewDidLoad() {
super.viewDidLoad()
self.addBackButton()
}
Note : if you don't add addBackButton Method in extension then you will need to add this method directly in the class and set target and Selector accordingly.