I am having troubles getting my cancel button to work. I have this action connected to my cancel button and I plan to dismiss the view controller like so:
#IBAction func cancel(sender: UIBarButtonItem) {
dismissViewControllerAnimated(true, completion: nil)
}
I was wondering what obvious bit I am missing. (This is a bar button item for a table view).
var b = UIBarButtonItem(title: "Cancel", style: .Plain, target: self, action: "Cancel clicked")
If you wanted the method to take the sender as a parameter, you would put a colon at the end:
var b = UIBarButtonItem(title: "Cancel", style: .Plain, target: self, action: "CancelClicked:")
func CancelClicked(sender: UIBarButtonItem) {
}
After you add the NavigationBar (and Navigation Item) to the Storyboard using IB, the reference to navigationItem var will be automatically mapped to your ViewController file. Add the code below to attach a cancel button to the navigationItem to dismiss the modal View Controller:
#IBOutlet weak var navigationBar: UINavigationBar!
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(cancelClicked(sender:)))
}
func cancelClicked(sender: UIBarButtonItem) {
print("Cancel clicked!")
self.dismiss(animated: true, completion: nil)
}
Try this:
#IBAction func close(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
Your code works fine with one little fix. Dismiss is called on the presenting controller. self.dismissViewController would dismiss child view controller presented by the current vc. but if you wanna dismiss the existing vc you should call dismiss on the parent
#IBAction func cancel(sender: UIBarButtonItem) {
presentingViewController.dismissViewControllerAnimated(true, completion: nil)
}
Related
In my app I have a push segue from HomeViewController to EditProfileViewController which should have a back button as a leftBarItem and a settings cog as a rightBarItem. The back button displays normally, but the right item is missing. These ViewControllers live happen in the MainNavigationController which has a Navigation Bar.
I tried to define the rightBarButton in ViewDidLoad of the EditProfileVC, I also tried to have a rightBarItem in the storyboard for the View controller.
let buttonItem = UIBarButtonItem(image: settingsIcon, style: .plain, target: self, action: #selector(settingsPressed))
buttonItem.tintColor = UIColor(.settingsIconTint)
navigationItem.rightBarButtonItem = buttonItem
Interestingly if I change the rightBar to a leftBar item, the back button is replaced with the settings cog and works as I expect, but I can't go back to the main page.
let buttonItem = UIBarButtonItem(image: settingsIcon, style: .plain, target: self, action: #selector(settingsPressed))
buttonItem.tintColor = UIColor(.settingsIconTint)
navigationItem.leftBarButtonItem = buttonItem
To set a rightBarButtonItem in a navigationBar,
class HomeViewController: UIViewController {
#IBAction func openEditVC(_ sender: UIButton) {
if let controller = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "EditProfileViewController") as? EditProfileViewController {
self.navigationController?.pushViewController(controller, animated: true)
}
}
}
class EditProfileViewController: UIViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let buttonItem = UIBarButtonItem(title: "Settings", style: .plain, target: self, action: #selector(settingsPressed))
buttonItem.tintColor = .red
navigationItem.rightBarButtonItem = buttonItem
}
#objc func settingsPressed() {
print("Setting Pressed")
}
}
In the above code I've added a UIBarButtonItem with title Settings as a rightBarButtonItem of navigationBar.
No need to configure leftBarButtonItem it not required. Back button is added by default.
Screenshot:
In case it doesn't satisfy your requirement, add a screenshot of what is expected so I can help.
I added an extension to UIViewController to add a close button
extension UIViewController {
func addCloseButton() {
let button = UIBarButtonItem(image: #imageLiteral(resourceName: "bar_close"),
landscapeImagePhone: nil,
style: .done,
target: self,
action: #selector(UIViewController.dismiss(animated:completion:)))
navigationItem.leftBarButtonItem = button
}
}
When i tap the barbutton i get a crash directly to AppDelegate.
Any hints? Seems related to the selector.
You can't use dismiss(animated:completion:) as selector here because it takes two arguments bool and closure and bar button action pass args as UIBarButtonItem which cause app crash.
so change your code like this.
extension UIViewController {
func addCloseButton() {
let button = UIBarButtonItem(image: #imageLiteral(resourceName: "rightgreen"),
landscapeImagePhone: nil,
style: .done,
target: self,
action: #selector(onClose))
navigationItem.leftBarButtonItem = button
}
#objc func onClose(){
self.dismiss(animated: true, completion: nil)
}
}
However this question has accepted answer which load extra one method addCloseButton in each and every viewcontroller still posting a answer will going to help someone
NOTE : This example for adding barbutton item automatically and also handle action for pop view controller.
As Protocol extension doesn't provide a to implement selector methods so to get the rid of it I have created this solution.
First thing you need is BaseVC which is subclass of UIViewController and all of your view controller going to be inherited by BaseVC like your class LoginVC:BaseVC ...
now declare protocol
protocol PopableClass {
func popSelf (animated:Bool)
}
extension PopableClass where Self : UIViewController {
func popSelf (animated:Bool) {
self.navigationController?.popViewController(animated: animated)
}
}
In your Base VC add two methods and call setupNavigationBar from viewDidLoad
func setupNavigationBar () {
if self is PopableClass {
let barbuttonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "back"), landscapeImagePhone: #imageLiteral(resourceName: "back"), style: .plain, target: self, action: #selector(popViewController))
self.navigationItem.leftBarButtonItem = barbuttonItem
}
}
//--------------------------------------------------------------------------------
#objc func popViewController () {
if self is PopableClass {
(self as! PopableClass).popSelf(animated: true)
}
}
You did it !!
Now in whatever class you need back button to pop view controller just use like this
class PushedClass: BaseVC,PopableClass
Hope it is helpful
I'm unable to detect on-click events on UIBarButtonItems in Swift 3. Can anyone help?. I need to perform a segue to another storyboard and view controller on clicking the UIBarButtonItem.
Swift 3.0:
override func viewDidLoad() {
super.viewDidLoad()
let controllerButton: UIBarButtonItem = UIBarButtonItem.init(title: "Next", style: .plain, target: self, action: #selector(ViewController.changeController))
self.navigationItem.rightBarButtonItem = controllerButton
}
func changeController() {
self.performSegue(withIdentifier: "Controller name segue", sender: AnyObject)
}
Please check this above code to for creating UIBarButtonItem and keep that on right navigation Item along with target and action.
Checkout sample code below:-
var b = UIBarButtonItem(
title: "Continue",
style: .plain,
target: self,
action: #selector(sayHello(sender:))
)
func sayHello(sender: UIBarButtonItem) {
}
I have a simple one for you guys. I have created a back button on a UITableviewController, and want to set that back button to my other UIViewController(NewTableViewController).
here i implemement back button
let newBackButton = UIBarButtonItem(title: "Back", style: UIBarButtonItemStyle.plain, target: self, action: #selector(NewTableViewController.back(sender:)))
self.navigationItem.leftBarButtonItem = newBackButton
and action is
func back(sender: UIBarButtonItem) {
// perform your custom action
//....
// go back to the previuos view controller
_ = navigationController?.navigationController?.self.dismiss(animated: true)
}
but i am unable to go back
Thanks for the help you guys. Please tell me what I am missing.
Try this for swift 3
If you use model view controller
func back(sender: UIBarButtonItem) {
self.dismiss(animated: true, completion: {});
}
OR
If you use push
func back(sender: UIBarButtonItem) {
if let navController = self.navigationController {
navController.popViewController(animated: true)
}
}
I understand how to set my UITableView into edit mode, and how to dynamically create an edit button:
override func viewDidLoad() {
tableView.allowsMultipleSelectionDuringEditing = true
tableView.setEditing(false, animated: false)
navigationItem.leftBarButtonItem = editButtonItem()
}
But when I tap the edit button, I would like a new button to appear on the navigation bar (i.e. a 'plus'/'add' button). To do this I think I need to create an IBAction, but I don't know how to link the editButtonItem() to an action. Any ideas?
Ok, big thanks to Ahmed and vadian for their comments, but what I got working was this:
override func setEditing(editing: Bool, animated: Bool) {
// Toggles the edit button state
super.setEditing(editing, animated: animated)
// Toggles the actual editing actions appearing on a table view
tableView.setEditing(editing, animated: true)
if (self.editing) {
navigationItem.rightBarButtonItem =
UIBarButtonItem(barButtonSystemItem: .Add, target: self,
action: #selector(clickMe))
} else {
// we're not in edit mode
let newButton = UIBarButtonItem(title: "", style: UIBarButtonItemStyle.Plain, target: navigationController, action: nil)
navigationItem.rightBarButtonItem = newButton
}
}
func clickMe()
{
print("Button Clicked")
}
As the edit button is pressed (and flips from Edit -> Done and back again) the code in the IF/ELSE statements will execute.
You can replace the default action of editButtonItem() by assigning a new function defined in your view controller to its action property.
editButtonItem().action = #selector(yourCustomAction(_:))
func yourCustomAction(sender: UIBarButtonItem) {}