Code for no text at back button at navigation bar - swift

I have the following code for letting the back button in my navigation bar stay with no text:
self.navigationController?.navigationBar.tintColor = UIColor.whiteColor()
let backItem = UIBarButtonItem(title: "", style: .Bordered, target: nil, action: nil)
navigationItem.backBarButtonItem = backItem
This worked until i updated xCode. Now I get this error message:
'Bordered' was deprecated in iOS version 8.0: Use UIBarButtonItemStylePlain when
minimum deployment target is iOS 7.0 or later.
thanks for your help

Just set the style to plain. Like this
let backItem = UIBarButtonItem(title: "", style: .Plain, target: nil, action: nil)
navigationItem.backBarButtonItem = backItem

Be careful. This technique works on every device except for an iPhone 6/6s Plus!
The common answer to this question is thus:
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .Plain, target: nil, action: nil)
Apple's documentation says to use nil for the title instead:
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: nil, style: .Plain, target: nil, action: nil)
Both techniques seem to work in all simulators and actual devices, save for the "iPhone plus". To rectify, without getting into creating your own Rects or similar cleverness, you can assign a single space to the title, as such:
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: " ", style: .Plain, target: nil, action: nil)
I don't like this answer, but it does work. The answer really should be setting the title to nil, as Apple documents. I can't believe such a large company could not have tested for that!

Related

How to Resize UIToolBar from a UIDatePicker?

I'm trying to show a UIDataPicker when the user clicks on the UITextField. It works. However, the size of it seems ridiculous.
Please, check this image from the simulator
It gives a warning regarding the constraints I've used in the storyboard:
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x6000036017c0 'TB_Trailing_Trailing' H:[_UIModernBarButton:0x7fa478418640'Cancel']-(0)-| (active, names: '|':_UIButtonBarButton:0x7fa478418470 )>
func showDatePicker() {
// Format date
bdPicker.datePickerMode = .date
//ToolBar
let toolbar = UIToolbar();
toolbar.sizeToFit()
let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(donedatePicker));
let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(cancelDatePicker));
toolbar.setItems([doneButton,spaceButton,cancelButton], animated: false)
BDTextField.inputAccessoryView = toolbar
BDTextField.inputView = bdPicker
}
I tried to modify: toolbar.sizeThatFits() and I gave random values, but the app crashed. So, I'm looking for a strategy that I can make this UIDatePicker fits half of the page at least.

Get returnKeyType text for UITextField

I am creating a custom UIToolBar to add as inputAccessoryView to a UITextField, I would like to add a UIBarButtonItem on the right side of this toolbar to serve as the return key of this textfield, and the text of this barButtonItem should be the same as the keyboard of that textfield.
My approach was:
let buttonDone = UIBarButtonItem(title: myTextField.returnKeyType, style: .done, target: self, action: #selector(pickerDone)
let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
// toolbar
let toolBar = UIToolbar()
toolBar.barStyle = .default
toolBar.items = [space, buttonDone]
toolBar.sizeToFit()
// setup input
myTextField.inputAccessoryView = toolBar
But with this i get this error:
Cannot convert value of type 'UIReturnKeyType?' to expected argument type 'String?'
So, I try something like:
title: myTextField.returnKeyType.text
But returnKeyType doesn't has a .text variable or similar...
Is there any way of doing this?
Should I go another way?
There is no built-in way to convert the UIReturnKeyType enum to a string. You will need to write your own code using a switch on the all the possible values.
Here's one solution using an extension. Add support for the other values as needed.
extension UIReturnKeyType {
var label: String {
switch self {
case .default:
return "Return"
case .go:
return "Go"
case .done:
return "Done"
default:
return "Enter"
}
}
}
Then you can use this as:
let buttonDone = UIBarButtonItem(title: myTextField.returnKeyType.label, style: .done, target: self, action: #selector(pickerDone)

NavigatorController Button not displaying popup alert

I was creating a simple Navigationcontroller Button to show an alert to click but it fails to do Please find the code below:
//Enable the buttons to edit
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Edit", style: .plain, target: self, action: #selector(EditEnable(sender:)))
#objc private func EditEnable(sender: UIBarButtonItem)
{
let alert = UIAlertController(title: "Time to change the Menu for Next Week",
message: "Message",
preferredStyle: UIAlertController.Style.alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertAction.Style.default))
}
Not sure what I am doing is wrong. Please help.
You're forgetting to show the alert.
self.present(alert, animated: true, completion: nil)

SWRevealController Programmatically

I am trying to use the SWRevealController programmatically by calling SWRevealController Delegate in my ViewController but when I add the following to viewDidLoad() the barButtonItem does not work and the app crashes when it hits addGestureRecognizer(self.revealViewController().panGestureRecognizer()). Below is the code in viewDidLoad:
navigationItem.leftBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "menu2-black-32").withRenderingMode(.alwaysOriginal), style: .plain, target: self.revealViewController(), action: #selector(SWRevealViewController.revealToggle(_:)))
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
I am not sure what's causing this issue as this code works for one of my viewcontrollers and none of the others.
Looks like my self.revealViewController() is nil when I've edited the code to look like this:
if self.revealViewController() != nil {
navigationItem.leftBarButtonItem = UIBarButtonItem(image:
#imageLiteral(resourceName: "menu2-black-
32").withRenderingMode(.alwaysOriginal), style: .plain, target:
self.revealViewController(), action:
#selector(SWRevealViewController.revealToggle(_:))) self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
But I am not sure why it's nil.
Firstly you need to create bar button
#IBOutlet weak var menuButton: UIBarButtonItem!
In viewDidLoad you can add this one
if self.revealViewController() != nil
{
menuButton.target = self.revealViewController()
menuButton.action = #selector(SWRevealViewController.revealToggle(_:))
self.view.addGestureRecognizer(self.revealViewController().tapGestureRecognizer())
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
This works fine you can also customise menuButton(UIBarButtonItem)

Swift 3 - Reload NavigationController Button Image

I have a navigation controller view, with an embedded collectionview controller. I have a right bar button added programmatically, with an image added to it as follows:
self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "greyCircle").withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector (handleGrayCircleButton))
I would like a user that clicks on this button, to be able to change the image from grey to silver. I have the button handler set up to switch from grey to silver with each press:
self.navigationItem.rightBarButtonItem?.image = UIImage(named: "greyCircle")
However, the image only changes briefly before switching back. I have tried to save the color of the image as a 'flag' variable, i.e. if it is currently grey, turn to silver, in order to make the change persist, however, the image continually resets to whatever it is loaded with (either with viewDidLoad or viewWillAppear).
Is there anyway to refresh/reload the navigationController tab bar after each click and make it persist, along with the images for the bar buttons?
#
EDIT: Following is full button handler.
func handleFavoritePress(){
print("Favorites pressed")
if(!returnTrueIfInFavorites(objectName: readString(object: self.patientRecord!, key: "name"), objectType: LIST_CoreDataBaseObjects.Patients)){
// Add to favorites
Favorites_Names.append(readString(object: self.patientRecord!, key: "name"))
Favorites_Types.append(LIST_CoreDataBaseObjects.Patients)
// Let user know
let patientName = readString(object: self.patientRecord!, key: "name")
let alertController = UIAlertController(title: "Alert!", message: "\(patientName) has been added to your favorites.", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alertController.addAction(defaultAction)
var rootViewController = UIApplication.shared.keyWindow?.rootViewController
if let navigationController = rootViewController as? UINavigationController {
rootViewController = navigationController.viewControllers.first
}
if let tabBarController = rootViewController as? UITabBarController {
rootViewController = tabBarController.selectedViewController
}
rootViewController?.present(alertController, animated: true, completion: nil)
self.navigationItem.rightBarButtonItem?.image = UIImage(named: "savedFavorite_1")
}else{
self.navigationItem.rightBarButtonItem?.image = UIImage(named: "favorite_2")
deleteFromFavorites(objectName: readString(object: patientRecord!, key: "name"), objectType: LIST_CoreDataBaseObjects.Patients)
}
for favorite in Favorites_Names{
print("Favorites are currently: \(patient)")
}
}
And other functions:
override func viewWillAppear(_ animated: Bool) {
collectionView?.backgroundView = setBackgroundImage(imageName: "whiteBackground")
navigationItem.title = "Patient"
if(returnTrueIfInFavorites(objectName: readString(object: patientRecord!, key: "name"), objectType: LIST_CoreDataBaseObjects.Patients)){
setupNavBarButtonsIsFavorited()
}else{
setupNavBarButtonsNotFavorited()
}
}
func setupNavBarButtonsNotFavorited(){
self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "favorite_2").withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector (handleFavoritePress))
}
func setupNavBarButtonsIsFavorited(){
self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "savedFavorite_1").withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector (handleFavoritePress))
}
The answer to your question lies within this two LIST_CoreDataBaseObjects.Patients, returnTrueIfInFavorites or the patientRecord variable.
Either LIST_CoreDataBaseObjects.Patients did not get updated on your function handleFavoritePress's code
/* this code */
Favorites_Names.append(readString(object: self.patientRecord!, key: "name"))
Favorites_Types.append(LIST_CoreDataBaseObjects.Patients)
/* this code */
Because from what you've explained in the comments section, if I understood it correctly, is that when you tap the button the image changes, and then you navigate to a different view, but then when you navigate back, viewDidAppear(_:) and viewWillAppear(_:) will be triggered.
Which in the code block below I will explain
// this function will be triggered everytime you navigate into this view (because it has appeared)
override func viewWillAppear(_ animated: Bool) {
/* don't forget to call super.viewWillAppear(true) */
super.viewWillAppear(true)
/* don't forget to call super.viewWillAppear(true) */
collectionView?.backgroundView = setBackgroundImage(imageName: "whiteBackground")
navigationItem.title = "Patient"
// the problem lies here
/* the function `(returnTrueIfInFavorites(objectName: readString(object: patientRecord!, key: "name"), objectType: LIST_CoreDataBaseObjects.Patients))` is always returning one thing which is why your image returns back to its previous state */
if (returnTrueIfInFavorites(objectName: readString(object: patientRecord!, key: "name"), objectType: LIST_CoreDataBaseObjects.Patients)) {
setupNavBarButtonsIsFavorited() // only one of these gets called
} else {
setupNavBarButtonsNotFavorited() // only one of these gets called
}
}
func setupNavBarButtonsNotFavorited() {
self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "favorite_2").withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector (handleFavoritePress))
}
func setupNavBarButtonsIsFavorited() {
self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "savedFavorite_1").withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector (handleFavoritePress))
}
All of these or you're just not updating the variable self.patientRecord!'s value (I haven't seen any setting in your code relating to this variable)