I have a UIViewController
with a UIBarButtonItem
configured to call my custom function called func settingsTapped(sender: AnyObject?)
in which I've put performSegueWithIdentifier
. I've determined that this function isn't being called even though the button DOES work and the segue somehow still works because it goes to the correct view controller.
First VC:
class CalculatorViewController: UIViewController {
private let timeInterval = 0.016 //how frequently we change the displayed number
private let animationLength = 0.3
private var timer: NSTimer?
private var counter: Int = 0
private var max: Double = 0.0
var startingPreferredUnits: String?
@IBOutlet weak var weightLifted: UITextField!
@IBOutlet weak var repetitions: UITextField!
@IBOutlet weak var oneRepMax: UILabel!
@IBOutlet weak var percentages: UITextView!
@IBOutlet weak var units: UILabel!
override func viewDidLoad() {
let settingsButton = UIBarButtonItem(title: "Settings", style: .Plain, target: self, action: #selector(settingsTapped(_:)))
self.navigationItem.leftBarButtonItem = settingsButton
super.viewDidLoad()
}
func settingsTapped(sender: AnyObject?) {
startingPreferredUnits = UserDefaultsManager.sharedInstance.preferredUnits
print("In segue, units is \(startingPreferredUnits)") // never prints this caveman debugging
self.performSegueWithIdentifier("segueToSettings", sender: self)
}
}
In the storyboard, I placed a Bar Button Item in the nav bar:
I created a Show (e.g. Push) segue between the Settings bar button item and the Settings view controller and I've given this segue an identifier of 'segueToSettings`. When I touch the Settings button, it does present the Settings view controller, but it doesn't print my caveman debugging line to the console.
I also tried creating the segue between the CalculatorViewController
itself and the SettingsViewController
(which I think may even be a better way) but when I have it set up that way, nothing happens at all when I touch the Settings button.
I've tried everything I could find on SO but nothing has worked. I hope I don't earn a Stupid Question badge on this one.
UPDATE 1:
I'm still struggling with this one. Here's something else I've learned and tried that didn't work. Clicking the Settings button works by performing the segue from the button to the Settings page which I created in the Storyboard. As one would expect, it will call override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
before doing this. So it's completely ignoring the action: #selector(settingsTapped(_:))
part. Also, I can change the identifier of the segue in the storyboard and it makes no difference at all. It still works. I can even delete the identifier and it works.
I also tried adding another button (this time a barButtonSystemItem
like so:
override func viewDidLoad() {
super.viewDidLoad()
let settingsButton = UIBarButtonItem(title: "Settings", style: .Plain, target: self, action: #selector(settingsTapped(_:)))
let saveButton = UIBarButtonItem(barButtonSystemItem: .Add, target: self, action: #selector(self.saveThisLift(_:)))
self.navigationItem.leftBarButtonItem = settingsButton
self.navigationItem.rightBarButtonItem = saveButton
}
func saveThisLift(sender: UIBarButtonItem) {
print("I'm in saveThisLift") // never prints
let weight = weightLifted.text
let reps = repetitions.text
let maxAmount = oneRepMax.text
let unitsText = units.description
coreDataStack.saveLiftEvent(currentLiftName!, formula: currentFormulaName!, weight: weight!, repetitions: reps!, maxAmount: maxAmount!, unitsUsed: unitsText)
}
func settingsTapped(sender: AnyObject?) {
startingPreferredUnits = UserDefaultsManager.sharedInstance.preferredUnits
print("In segue, units is \(startingPreferredUnits)") // never prints this caveman debugging
self.performSegueWithIdentifier("segueToSettings", sender: self)
}
Like the Settings button, touching it does nothing except make it flash. I should point out that I added the bar button items via the storyboard and I think that's unnecessary since I'm trying to add them programmatically. However, without them, neither of the buttons appears.
After a lot more research and more trial and error, I've figured it out. I learned a number of things that I'll leave here for anyone who has this problem in the future.
At a high-level, trying to do some of this in the storyboard and some in code made it easy to get confused. The key things for me were:
UINavigationController
with its out-of-the-box root view controller, I was dealing with a UIViewController
. With the UINavigationController
, you don't have to do as much. But with a UIViewController
, I had to add a UINavigationBar
and to that, I had to add a single UINavigationItem
. I did this by dragging them from the Object Library to my storyboard.UILabel
in the UINavigationBar
to do what I was trying to do, which was have them call custom functions. Trust me, it doesn't work, at least not in my case.UINavigationItem
, the next ah-ha! moment for me was the fact that I could put multiple UIBarButtonItems
in it (note: my example in my question shows just one to keep it simple but I'm actually adding three items)UINavigationItem
to my view controller and created an @IBOutlet called @IBOutlet weak var navItem: UINavigationItem!
_
class CalculatorViewController: UIViewController {
@IBOutlet weak var navItem: UINavigationItem!
override func viewDidLoad() {
super.viewDidLoad()
let settingsButton = UIBarButtonItem(title: "Settings", style: .Plain, target: self, action: #selector(self.segueToSettings(_:)))
let viewLogButton = UIBarButtonItem(title: "Log", style: .Plain, target: self, action: #selector(self.segueToLog(_:)))
let saveButton = UIBarButtonItem(barButtonSystemItem: .Add, target: self, action: #selector(self.saveLift(_:)))
self.navItem.leftBarButtonItem = settingsButton
self.navItem.rightBarButtonItems = [saveButton, viewLogButton]
}
func saveLift(sender: AnyObject) {
let weight = weightLifted.text
let reps = repetitions.text
let maxAmount = oneRepMax.text
let unitsText = units.text
coreDataStack.saveLiftEvent(currentLiftName!, formula: currentFormulaName!, weight: weight!, repetitions: reps!, maxAmount: maxAmount!, unitsUsed: unitsText!)
performSegueWithIdentifier("segueToLog", sender: self)
}
}
Lastly, when you create that @IBOutlet, don't name it navigationItem: UINavigationItem
because that will make Xcode very unhappy:
I burned a lot of hours on this one. I hope this information helps somebody avoid that in the future.