programmatically embedding segmented control inside navigation bar - swift

I am trying to insert a segmented control inside a navigation bar programmatically and am having some trouble loading the segmented controller in the nav bar. I am sure this very simple, but see code below. Thanks in advance!
var segmentedController: UISegmentedControl!
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.titleView = segmentedController
let items = ["Label A", "Label B"]
segmentedController = UISegmentedControl(items: items)
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Sign Out", style: .plain, target: self, action: #selector(handleSignOut))
navigationItem.leftBarButtonItem?.tintColor = UIColor.black
}

You should add the segmentedController to the navigation bar after initializing it!
var segmentedController: UISegmentedControl!
override func viewDidLoad() {
super.viewDidLoad()
let items = ["Label A", "Label B"]
segmentedController = UISegmentedControl(items: items)
navigationItem.titleView = segmentedController
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Sign Out", style: .plain, target: self, action: #selector(handleSignOut))
navigationItem.leftBarButtonItem?.tintColor = UIColor.black
}

Related

cannot create UIBarButtonItem on viewcontroller

I'm trying to add a UIBarButtonItem by doing this function:
func setupBackButton() {
let button = UIButton(type: .custom)
button.setTitle("Done", for: .normal)
button.titleLabel?.font = .systemFont(ofSize: 40)
let barButton = UIBarButtonItem(customView: button)
//assign button to navigationbar
self.navigationItem.leftBarButtonItem = barButton
}
it works on other screens that i add it,
but on a spefic view controller it just doens't add anything.
Here is the storyboard of other screens that it works on them :
And here is the sotryboard in the screen that Doesn't work:
what might be the problem , and why i might not see the button ?
swift 4:
I added a navigation controller:
create UIBarButtonItem on viewcontroller :
override func viewDidLoad() {
super.viewDidLoad()
let leftBarButton = UIBarButtonItem(title: "Edit", style: .done, target: self, action: #selector(myLeftBarButtonItem(_:)))
self.navigationItem.leftBarButtonItem = leftBarButton
}
#objc func myLeftBarButtonItem(_ sender:UIBarButtonItem!) {
print("myLeftBarButtonItem")
}
You may try this:
if you add image in left navbar then write this :
let leftAddBarButtonItemMenu = UIBarButtonItem(image: #imageLiteral(resourceName: "menu"), style: UIBarButtonItemStyle.plain, target: self, action: #selector(self.btnLeftMenuClicked(sender:)))
navigationItem.leftBarButtonItems = [leftAddBarButtonItemMenu]
if you add image in right navbar then write this :
let rightNavBarItem = UIBarButtonItem(image: #imageLiteral(resourceName: "menu"), style: UIBarButtonItemStyle.plain, target: self, action: #selector(self.btnRightClicked(sender:)))
navigationItem.rightBarButtonItem = [rightNavBarItem]
If add Title in right navbar then write this:
let rightNavBarItem = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.plain, target: self, action: #selector(self.btnRightClicked(sender:)))
navigationItem.rightBarButtonItem = [rightNavBarItem]
It may Helps you. Thank you

UIBarButtonItem selector not working

I have a MainViewController embed in a Navigation Controller, as shown below:
And in MainViewController.swift, I added two UIBarButtonItem(left and right) programmatically:
class MainViewController: UIViewController {
let rightButton = UIBarButtonItem(title: "Right", style: .plain, target: self, action: #selector(onRightClick))
let leftButton = UIBarButtonItem(title: "Left", style: .plain, target: self, action: #selector(onLeftClick))
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.rightBarButtonItem = rightButton
navigationItem.leftBarButtonItem = leftButton
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#objc func onRightClick() {
print("[Main] Right Click")
}
#objc func onLeftClick() {
print("[Main] Left Click")
}
}
The buttons did show on the screen, but the interesting thing is, the selector functions onLeftClick and onRightClick never get called whenever I pressed left or right button. Is there anything I should do to make it works? I am using Xcode 9.3.
try with inside scope once
override func viewDidLoad() {
super.viewDidLoad()
let rightButton = UIBarButtonItem(title: "Right", style: .plain, target: self, action: #selector(self.onRightLeftClick(_ :)))
rightButton.tag = 1
let leftButton = UIBarButtonItem(title: "Left", style: .plain, target: self, action: #selector(self.onRightLeftClick(_ :)))
rightButton.tag = 2
self.navigationItem.rightBarButtonItem = rightButton
self.navigationItem.leftBarButtonItem = leftButton
}
handle the action as
func onRightLeftClick(_ sender: UIBarButtonItem){
if sender.tag == 1{
// rightButton action
}else{
// leftButton action
}
}
You can also just add the lazy keyword to the rightButton and leftButton class properties. That way, the UIBarButtonItem won't be instantiated (and the action selectors won't attempt to be resolved) until they are used inside the class. Doing it this way allows you to use the barButtonItems anywhere in the class (not just in the function they are declared in).
lazy var rightButton = UIBarButtonItem(title: "Right", style: .plain, target: self, action: #selector(onRightClick))
lazy var leftButton = UIBarButtonItem(title: "Left", style: .plain, target: self, action: #selector(onLeftClick))

Add action to UIBarButtonItem dynamically Swift 4

let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.plain, target: self, action: #selector(buttonClicked(sender:)))
#objc func buttonClicked(sender: UIBarButtonItem) {
print("Hello")
}
That's the code for my UIBarButton but when I click on it it doesn't print "Hello", what could be the problem?
EDIT: Here are my viewcontroller
It simply control a button that when it's clicked show the spinner with its control, but as I said before the button on toolbar doesn't work
class FilterViewController: UIViewController {
var search: Search?
let categoriesSpinnerDelegate = CategoriesPickerDelegate()
#IBOutlet weak var generalSpinner: UIPickerView!
#IBOutlet weak var categoriesButton: UIButton!
#IBOutlet weak var categoryRow: UIView!
var doneButton: UIBarButtonItem?
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.topViewController?.title = "Filtri"
// Set border and click action
self.categoryRow.layer.borderWidth = 1
self.categoryRow.layer.borderColor = Raccoltacase.lightGray.cgColor
self.categoryRow.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.buttonClicked(sender:))))
// Create toolbar and attach it to pickerView
let toolBar = UIToolbar()
toolBar.barStyle = UIBarStyle.default
toolBar.isTranslucent = true
//toolBar.tintColor = UIColor(red: 76/255, green: 217/255, blue: 100/255, alpha: 1)
toolBar.sizeToFit()
self.doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.plain, target: self, action: #selector(buttonClicked(sender:)))
let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.plain, target: self, action: nil)
toolBar.setItems([cancelButton, spaceButton, doneButton!], animated: false)
toolBar.isUserInteractionEnabled = true
generalSpinner.addSubview(toolBar)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func categoriesButtonClick(_ sender: UIButton) {
self.generalSpinner.showsSelectionIndicator = true
self.generalSpinner.dataSource = categoriesSpinnerDelegate
self.generalSpinner.delegate = categoriesSpinnerDelegate
self.generalSpinner.isHidden = false
}
#objc func buttonClicked(sender: UIBarButtonItem) {
print("Hello")
}
}
Screen
Assuming that you are showing the picker sometimes (and dismissing it when user presses the done button), here is my solution:
Add a UITextField to the view in storyboard (and make the tintColor transparent (clearColor))
Add the UIToolbar as inputAccessoryView to the UITextField
Add the UIPickerView as inputView to the toolbar (Also see the note below)
Below is a sample code:
override func viewDidLoad() {
super.viewDidLoad()
textField.inputView = generalSpinner
textField.inputAccessoryView = getToolbar()
}
func getToolbar() -> UIToolbar {
let toolBar = UIToolbar(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 40))
toolBar.barStyle = UIBarStyle.default
toolBar.isTranslucent = true
self.doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.plain, target: self, action: #selector(buttonClicked(sender:)))
let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.plain, target: self, action: nil)
toolBar.setItems([cancelButton, spaceButton, doneButton!], animated: false)
toolBar.isUserInteractionEnabled = true
return toolBar
}
Note: In case the UIPickerView is already in the storyboard (or a subview of another view), make sure to remove it in the first line of viewDidLoad (as shown below):
override func viewDidLoad() {
super.viewDidLoad()
generalSpinner.removeFromSuperview()
textField.inputView = generalSpinner
textField.inputAccessoryView = getToolbar()
}
SOLVED
When i use pickerView.addSubView(toolbar) the toolbar was placed behind the pickerview and so it was no clickable. I solved it adding the toolbar manually from storyboard with General Spinner.top = Picker Toolbar.bottom

NavigationBar title with two UIBarButtons

I'm trying to set the title of the UINavigationBar. If i don't add the UIBarButtons, i can see the title, if i add them, i can't. I want to see both
var cancelBarButtonItem = UIBarButtonItem(
title: "Cancel".localized,
style: .plain,
target: self,
action: #selector(cancelButtonTouched(sender:))
)
var doneBarButtonItem = UIBarButtonItem(
title: "Done",
style: .plain,
target: self,
action: #selector(doneButtonTouched(sender:))
)
override func viewDidLoad() {
super.viewDidLoad()
setupRightNavBarButtons()
self.navigationController?.navigationBar.topItem?.title = "Title"
}
func setupRightNavBarButtons(){
self.doneBarButtonItem.isEnabled = false
navigationItem.leftBarButtonItem = cancelBarButtonItem
navigationItem.rightBarButtonItem = doneBarButtonItem
}
The proper way for a view controller to set itself up for the navigation bar is to set its own navigationItem.
Change:
self.navigationController?.navigationBar.topItem?.title = "Title"
to:
self.title = "Title" // sets the navigationItem title
or:
navigationItem.title = "Title"

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")
}