multiple UIDatePicker one uitextfield - ios

In my ViewController there are several UiTextfield.
I intend to use a single UIDatePicker that is expected to respond accordingly.
my code only responds to event generated by second textfield and not the first one.
I just need to determine which UITextField has generated the event...
import UIKit
class ViewController: UIViewController , UITextFieldDelegate {
var datePicker = UIDatePicker()
#IBOutlet weak var tvDueDate: UITextField!
#IBOutlet weak var tvOtherDate: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//setupDatePicker()
self.tvDueDate.tag = 0
self.tvOtherDate.tag = 1
//setupDatePicker(textField)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func textFieldDidEndEditing(textField: UITextField) {
setupDatePicker(textField)
}
func textFieldDidBeginEditing(textField: UITextField) {
setupDatePicker(textField)
}
func setupDatePicker(text: UITextField) {
// Sets up the "button"
//tvDueDate.text = "Pick a due date"
//tvDueDate.textAlignment = .Center
// Removes the indicator of the UITextField
//tvDueDate.tintColor = UIColor.clearColor()
// Specifies intput type
datePicker.datePickerMode = .Date
// Creates the toolbar
let toolBar = UIToolbar()
toolBar.barStyle = .Default
toolBar.translucent = true
toolBar.tintColor = UIColor(red: 92/255, green: 216/255, blue: 255/255, alpha: 1)
toolBar.sizeToFit()
// Adds the buttons
var doneButton = UIBarButtonItem(title: "Done", style: .Plain, target: self, action: "doneClick")
var spaceButton = UIBarButtonItem(barButtonSystemItem: .FlexibleSpace, target: nil, action: nil)
var cancelButton = UIBarButtonItem(title: "Cancel", style: .Plain, target: self, action: "cancelClick")
toolBar.setItems([cancelButton, spaceButton, doneButton], animated: false)
toolBar.userInteractionEnabled = true
// Adds the toolbar to the view
if text.tag == 0{
self.tvDueDate.inputView = datePicker
self.tvDueDate.inputAccessoryView = toolBar
}
else
{
self.tvOtherDate.inputView = datePicker
self.tvOtherDate.inputAccessoryView = toolBar
}
}
func doneClick() {
var dateFormatter = NSDateFormatter()
//dateFormatter.dateFormat = "dd-MM-yyyy"
dateFormatter.dateStyle = .ShortStyle
if tvDueDate.isFirstResponder(){
tvDueDate.text = dateFormatter.stringFromDate(datePicker.date)
tvDueDate.resignFirstResponder()
}else{
tvOtherDate.text = dateFormatter.stringFromDate(datePicker.date)
tvOtherDate.resignFirstResponder()
}
}
func cancelClick() {
if tvDueDate.isFirstResponder(){
tvDueDate.resignFirstResponder()
}else{
tvOtherDate.resignFirstResponder()
}
}
}

Give unique tags to your UITextFields and use UITextField delegates.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//setupDatePicker()
self.tvDueDate.tag = 0
self.tvOtherDate.tag = 1
self.tvDueDate.delegate = self
self.tvOtherDate.delegate = self
//setupDatePicker(textField)
}
// UITextField Delegates
func textFieldDidBeginEditing(textField: UITextField) {
println("TextField did begin editing method called")
if textField.tag == 0
..........
if textField.tag == 2
....
}
func textFieldDidEndEditing(textField: UITextField) {
println("TextField did end editing method called")
}
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
println("TextField should begin editing method called")
return true;
}

You are calling
setupDatePicker()
From viewDidLoad and your code is
if tvDueDate.isFirstResponder(){
tvDueDate.inputView = datePicker
tvDueDate.inputAccessoryView = toolBar
}
else
{
tvOtherDate.inputView = datePicker
tvOtherDate.inputAccessoryView = toolBar
}
adds picker as inputAccessoryView . As at the point of viewDidLoad no text field is FirstResponder that's why only your else part is excited and its only added to tvOtherDate field.
I would recommend to call it from the textfield delegate method (will begin editing or didbegineditting) or call it on tap. And to check from which it is called also pass the textfield or you can use tag.

Adding Delegates and tags to my UiTextField helped me.......
import UIKit
class ViewController: UIViewController , UITextFieldDelegate {
var datePicker = UIDatePicker()
#IBOutlet weak var tvDueDate: UITextField!
#IBOutlet weak var tvOtherDate: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//setupDatePicker()
self.tvDueDate.tag = 0
self.tvOtherDate.tag = 1
//setupDatePicker(textField)
self.tvDueDate.delegate = self
self.tvOtherDate.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func textFieldDidEndEditing(textField: UITextField) {
setupDatePicker(textField)
}
func textFieldDidBeginEditing(textField: UITextField) {
setupDatePicker(textField)
}
func setupDatePicker(text: UITextField) {
// Sets up the "button"
//tvDueDate.text = "Pick a due date"
//tvDueDate.textAlignment = .Center
// Removes the indicator of the UITextField
//tvDueDate.tintColor = UIColor.clearColor()
// Specifies intput type
datePicker.datePickerMode = .Date
// Creates the toolbar
let toolBar = UIToolbar()
toolBar.barStyle = .Default
toolBar.translucent = true
toolBar.tintColor = UIColor(red: 92/255, green: 216/255, blue: 255/255, alpha: 1)
toolBar.sizeToFit()
// Adds the buttons
var doneButton = UIBarButtonItem(title: "Done", style: .Plain, target: self, action: "doneClick")
var spaceButton = UIBarButtonItem(barButtonSystemItem: .FlexibleSpace, target: nil, action: nil)
var cancelButton = UIBarButtonItem(title: "Cancel", style: .Plain, target: self, action: "cancelClick")
toolBar.setItems([cancelButton, spaceButton, doneButton], animated: false)
toolBar.userInteractionEnabled = true
// Adds the toolbar to the view
if text.tag == 0{
self.tvDueDate.inputView = datePicker
self.tvDueDate.inputAccessoryView = toolBar
}
else
{
self.tvOtherDate.inputView = datePicker
self.tvOtherDate.inputAccessoryView = toolBar
}
}
func doneClick() {
var dateFormatter = NSDateFormatter()
//dateFormatter.dateFormat = "dd-MM-yyyy"
dateFormatter.dateStyle = .ShortStyle
if tvDueDate.isFirstResponder(){
tvDueDate.text = dateFormatter.stringFromDate(datePicker.date)
tvDueDate.resignFirstResponder()
}else{
tvOtherDate.text = dateFormatter.stringFromDate(datePicker.date)
tvOtherDate.resignFirstResponder()
}
}
func cancelClick() {
if tvDueDate.isFirstResponder(){
tvDueDate.resignFirstResponder()
}else{
tvOtherDate.resignFirstResponder()
}
}
}

Related

DatePicker passing data

I have a successful date picker and on the following page a stepper/number picker that allows users to select dates, and item quantities. In a new view, I would like to display all the previous information for them to review. I have a few methods in place but they don't seem to work. I am guessing it is because they aren't textFields, and some extra code is needed in order to ask the UIdatepicker and Stepper to pass the information. Take a look below please :)
Here is my date picker View Controller
import UIKit
class StoreDatesViewController: UIViewController {
#IBOutlet weak var nextButton: UIButton!
#IBOutlet weak var dropOff: UITextField!
#IBOutlet weak var pickUp: UITextField!
let datePicker = UIDatePicker()
override func viewDidLoad() {
super.viewDidLoad()
showDatePicker()
}
override func viewWillAppear(_ animated: Bool) {
nextButton.isEnabled = true
}
func showDatePicker(){
//Format Date
datePicker.datePickerMode = .date
datePicker.preferredDatePickerStyle = .inline
datePicker.backgroundColor = UIColor(named: "yellow-2")
//ToolBar
let toolbar = UIToolbar();
toolbar.sizeToFit()
let toolbar2 = UIToolbar();
toolbar2.sizeToFit()
let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(donedatePicker));
let cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(cancelDatePicker));
let doneButton2 = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(donedatePicker2));
let cancelButton2 = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(cancelDatePicker2));
toolbar.setItems([doneButton,cancelButton], animated: false)
toolbar.tintColor = .white
toolbar.backgroundColor = .red
toolbar2.setItems([doneButton2,cancelButton2], animated: false)
toolbar2.tintColor = .white
dropOff.inputAccessoryView = toolbar
dropOff.inputView = datePicker
pickUp.inputAccessoryView = toolbar2
pickUp.inputView = datePicker
}
#objc func donedatePicker(){
let formatter = DateFormatter()
formatter.dateFormat = "dd/MM/yyyy"
dropOff.text = formatter.string(from: datePicker.date)
self.view.endEditing(true)
}
#objc func donedatePicker2(){
let formatter = DateFormatter()
formatter.dateFormat = "dd/MM/yyyy"
pickUp.text = formatter.string(from: datePicker.date)
self.view.endEditing(true)
}
#objc func cancelDatePicker(){
self.view.endEditing(true)
}
#objc func cancelDatePicker2(){
self.view.endEditing(true)
}
#IBAction func didTapNext() {
let dropOff = dropOff.text
let pickUp = pickUp.text
let storeDetailsVC = self.storyboard?.instantiateViewController(withIdentifier: "storeDetailsVC") as! storeDetailsViewController
storeDetailsVC.dropOff = dropOff!
storeDetailsVC.pickUp = pickUp!
}
}
Here is my number Pick View Controller
import UIKit
class StoreQuantityViewController: UIViewController{
#IBOutlet weak var numbers: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func stepper(_ sender: UIStepper) {
numbers.text = String(Int(sender.value))
}
#IBAction func next(_ sender: Any) {
let data2 = numbers.text
let storeDetailsVC = self.storyboard?.instantiateViewController(withIdentifier: "storeDetailsVC") as! storeDetailsViewController
storeDetailsVC.data2 = data2!
self.navigationController?.pushViewController(storeDetailsVC, animated: true)
}
}
```
You need to pass the information from text fields to Strings in the next View.
Solution 1:
override func viewDidLoad() {
super.viewDidLoad()
pickUp.text = currentDate // This you can create using the date formatter
dropOff.text = defaultDate // This is default date value you can set if needed
showDatePicker()
}
Solution 2:
#IBAction func didTapNext() {
//Apply validation here to check if its empty if no default value provided.
if dropOff.text.isEmpty {
//Show alert to user to select drof off date.
return
}
if pickUp.text.isEmpty {
//Show alert to user to select PickUp date.
return
}
let dropOff = dropOff.text
let pickUp = pickUp.text
let storeDetailsVC = self.storyboard?.instantiateViewController(withIdentifier: "storeDetailsVC") as! storeDetailsViewController
storeDetailsVC.dropOff = dropOff!
storeDetailsVC.pickUp = pickUp!
}

I can't pass data between classes using callback as completion handler

I want to pass text of textField in custom class to ViewController and populate it to array when BarButtonItem of DatePicker is tapped. I used a callback as completion handler, but it caught EXC-BAD-ACCESS. What made this error and how could I pass text to my ViewController?
Custom class of textField
class HourDatePicker: UITextField {
var datePicker = UIDatePicker()
override init(frame: CGRect) {
super.init(frame: frame)
commominit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commominit()
}
func commominit(){
text = ""
datePicker.datePickerMode = .dateAndTime
datePicker.minuteInterval = 30
datePicker.locale = Locale(identifier: "ja")
datePicker.addTarget(self, action: #selector(setText), for: .valueChanged)
setText()
inputView = datePicker
inputAccessoryView = customPicker()
}
#objc func setText(){
let f = DateFormatter()
f.dateStyle = .full
f.timeStyle = .short
f.locale = Locale(identifier: "ja")
textColor = .black
text = "\(f.string(from: datePicker.date))"
}
private func customPicker() -> UIToolbar {
let toolbar = UIToolbar()
toolbar.frame = CGRect(x: 0, y: 0, width: self.frame.size.width, height: 40)
let space = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: self, action: nil)
space.width = 100
let flexSpaceItem = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
let todayButtonItem = UIBarButtonItem(title: "today", style: .done, target: self, action: #selector(setToday))
let selectButtonItem = UIBarButtonItem(title: "select", style: .done, target: self, action: #selector(tellCalenderText))
let toolbarItem = [space, flexSpaceItem, todayButtonItem, selectButtonItem]
toolbar.setItems(toolbarItem, animated: true)
}
return toolbar
}
#objc func tellCalenderText(completion: ((_ titleText: String) -> Void)){
//I want to pass text here.
if text != "" {
guard let titleText = text else {return}
completion(titleText)
} else {
return
}
}
ViewController
class Calender1ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
private let selectDate = HourDatePicker()
private var keepDate: [String] = []
#IBOutlet weak var timeTextView: UITextView!
#IBOutlet weak var dateText: HourDatePicker!
#IBOutlet weak var calenderTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.calenderTableView.delegate = self
self.calenderTableView.dataSource = self
selectDate.tellCalenderText {[weak self] (titleText) in
self?.bringDate(title: titleText)
}
}
func bringDate(title: String){
print("title: \(title)")
self.keepDate.append(title)
timeTextView.text.append(contentsOf: "\(title)\n")
}
Thank you.
This is error log.
error log
First, I think you're getting a bit messed up by having:
private let selectDate = HourDatePicker()
and having:
#IBOutlet weak var dateText: HourDatePicker!
and then making use of selectDate inside viewDidLoad()...
Give this a try. I only made a few changes, and tried to include enough comments to make it clear. I think you'll find this a much more straight-forward way of getting your custom HourDatePicker class to pass information back to the view controller:
class HourDatePicker: UITextField {
var datePicker = UIDatePicker()
override init(frame: CGRect) {
super.init(frame: frame)
commominit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commominit()
}
func commominit(){
text = ""
datePicker.datePickerMode = .dateAndTime
datePicker.minuteInterval = 30
datePicker.locale = Locale(identifier: "ja")
datePicker.addTarget(self, action: #selector(setText), for: .valueChanged)
setText()
inputView = datePicker
inputAccessoryView = customPicker()
}
#objc func setToday(){
datePicker.date = Date()
}
#objc func setText(){
let f = DateFormatter()
f.dateStyle = .full
f.timeStyle = .short
f.locale = Locale(identifier: "ja")
textColor = .black
text = "\(f.string(from: datePicker.date))"
}
private func customPicker() -> UIToolbar {
let toolbar = UIToolbar()
toolbar.frame = CGRect(x: 0, y: 0, width: self.frame.size.width, height: 40)
let space = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: self, action: nil)
space.width = 100
let flexSpaceItem = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
let todayButtonItem = UIBarButtonItem(title: "today", style: .done, target: self, action: #selector(setToday))
let selectButtonItem = UIBarButtonItem(title: "select", style: .done, target: self, action: #selector(tellCalenderText))
let toolbarItem = [space, flexSpaceItem, todayButtonItem, selectButtonItem]
toolbar.setItems(toolbarItem, animated: true)
return toolbar
}
// "callback" closure
var tellController: ((String) ->())?
// triggered by "select" bar button tap
#objc func tellCalenderText() -> Void {
// get text from self
guard let t = text else {
return
}
// execute the callback closure
tellController?(t)
}
// #objc func tellCalenderText(completion: ((_ titleText: String) -> Void)){
// //I want to pass text here.
// if text != "" {
// guard let titleText = text else {return}
// completion(titleText)
// } else {
// return
// }
//
// }
}
//ViewController
class Calender1ViewController: UIViewController {
// not needed
//private let selectDate = HourDatePicker()
private var keepDate: [String] = []
// UITextView connected via Storyboard
#IBOutlet weak var timeTextView: UITextView!
// UITextField set to HourDatePicker, connected via Storyboard
#IBOutlet weak var dateText: HourDatePicker!
#IBOutlet weak var calenderTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// set the callback closure for the HourDatePicker
dateText.tellController = { [weak self] (titleText) in
self?.bringDate(title: titleText)
}
// not needed
//selectDate.tellCalenderText {[weak self] (titleText) in
// self?.bringDate(title: titleText)
//}
}
func bringDate(title: String){
print("title: \(title)")
self.keepDate.append(title)
timeTextView.text.append(contentsOf: "\(title)\n")
}
}

Why #selector doesn't call handler method for iPad's keyboard shortcuts?

I have a class for constructing UIBarButtonItems:
enum KeyboardToolbarButton: Int {
case done = 0
case cancel
case back, backDisabled
case forward, forwardDisabled
func createButton(target: Any?, action: Selector?) -> UIBarButtonItem {
var button: UIBarButtonItem!
switch self {
case .back:
button = UIBarButtonItem(title: "<=", style: .plain, target: target, action: action)
case .backDisabled:
button = UIBarButtonItem(title: "<=", style: .plain, target: target, action: action)
button.isEnabled = false
case .forward:
button = UIBarButtonItem(title: "=>", style: .plain, target: target, action: action)
case .forwardDisabled:
button = UIBarButtonItem(title: "=>", style: .plain, target: target, action: action)
button.isEnabled = false
case .done:
button = UIBarButtonItem(title: "DONE", style: .plain, target: target, action: action)
case .cancel:
button = UIBarButtonItem(title: "CANCEL", style: .plain, target: target, action: action)
}
button.tag = rawValue
return button
}
static func detectType(barButton: UIBarButtonItem) -> KeyboardToolbarButton? {
return KeyboardToolbarButton(rawValue: barButton.tag)
}
}
Class for constructing KeyboardToolbar from KeyboardToolbarButton:
class KeyboardToolbar {
weak var toolBarDelegate: KeyboardToolbarDelegate?
var textField: UITextField!
init(textField: UITextField) {
self.textField = textField
self.textField.autocorrectionType = .no
self.textField.inputAssistantItem.leadingBarButtonGroups = []
self.textField.inputAssistantItem.trailingBarButtonGroups = []
}
func setup(leftButtons: [KeyboardToolbarButton], rightButtons: [KeyboardToolbarButton]) {
let leftBarButtons = leftButtons.map { (item) -> UIBarButtonItem in
return item.createButton(target: self, action: #selector(self.buttonTapped(sender:)))
}
let rightBarButtons = rightButtons.map { (item) -> UIBarButtonItem in
return item.createButton(target: self, action: #selector(self.buttonTapped(sender:)))
}
let groupLeading: UIBarButtonItemGroup = UIBarButtonItemGroup.init(barButtonItems: leftBarButtons, representativeItem: nil)
let groupTrailing: UIBarButtonItemGroup = UIBarButtonItemGroup.init(barButtonItems: rightBarButtons, representativeItem: nil)
textField.inputAssistantItem.leadingBarButtonGroups.append(groupLeading)
textField.inputAssistantItem.trailingBarButtonGroups.append(groupTrailing)
}
#objc func buttonTapped(sender: UIBarButtonItem) {
if let type = KeyboardToolbarButton.detectType(barButton: sender) {
print(type)
toolBarDelegate?.keyboardToolbar(button: sender, type: type, tappedIn: self)
}
}
}
And delegate:
protocol KeyboardToolbarDelegate: class {
func keyboardToolbar(button: UIBarButtonItem, type: KeyboardToolbarButton, tappedIn toolbar: KeyboardToolbar)
}
Here's how I use KeyboardToolbar:
class ViewController: UIViewController {
#IBOutlet weak var textField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
addButtons(for: textField, setLeftButtons: [.back, .forward], andRightButtons: [.done])
}
private func addButtons(for textField: UITextField, setLeftButtons leftButtons: [KeyboardToolbarButton] = [], andRightButtons rightButtons: [KeyboardToolbarButton] = []) {
let toolbar = KeyboardToolbar(textField: textField)
toolbar.toolBarDelegate = self
toolbar.setup(leftButtons: leftButtons, rightButtons: rightButtons)
}
}
extension ViewController: KeyboardToolbarDelegate {
func keyboardToolbar(button: UIBarButtonItem, type: KeyboardToolbarButton, tappedIn toolbar: KeyboardToolbar) {
print("Tapped button type: \(type)")
}
}
Here's how it works (this feature available only on iPad)
So, the problem is that #objc func buttonTapped(sender: UIBarButtonItem) never calls. So, #selector(self.buttonTapped(sender:) does not connect to handler. How to fix it?
Update:
According to the answer of Taras Chernyshenko, I added KeyboardToolbar as a member of ViewController:
class ViewController: UIViewController {
#IBOutlet weak var textField: UITextField!
var toolbar: KeyboardToolbar!
override func viewDidLoad() {
super.viewDidLoad()
addButtons(for: textField, setLeftButtons: [.back, .forward], andRightButtons: [.done])
}
private func addButtons(for textField: UITextField, setLeftButtons leftButtons: [KeyboardToolbarButton] = [], andRightButtons rightButtons: [KeyboardToolbarButton] = []) {
toolbar = KeyboardToolbar(textField: textField)
toolbar.toolBarDelegate = self
toolbar.setup(leftButtons: leftButtons, rightButtons: rightButtons)
}
}
Problem is in you design. In KeyboardToolbar class in func setup(leftButtons:, rightButtons:) function you doing next:
let leftBarButtons = leftButtons.map { (item) -> UIBarButtonItem in
return item.createButton(target: self, action: #selector(self.buttonTapped(sender:)))
}
here you are setting action target to KeyboardToolbar class.
Next in addButtons(for textField:, setLeftButtons leftButtons:, andRightButtons rightButtons:) of ViewController you setup your buttons like
let toolbar = KeyboardToolbar(textField: textField)
toolbar.toolBarDelegate = self
toolbar.setup(leftButtons: leftButtons, rightButtons: rightButtons)
but after this function toolbar is dealocated, so actions can't reach their target.
To simple fix, store toolbar into class property
class ViewController: UIViewController {
#IBOutlet weak var textField: UITextField!
var toolbar = KeyboardToolbar?
override func viewDidLoad() {
super.viewDidLoad()
addButtons(for: textField, setLeftButtons: [.back, .forward], andRightButtons: [.done])
}
private func addButtons(for textField: UITextField, setLeftButtons leftButtons: [KeyboardToolbarButton] = [], andRightButtons rightButtons: [KeyboardToolbarButton] = []) {
let toolbar = KeyboardToolbar(textField: textField)
toolbar.toolBarDelegate = self
toolbar.setup(leftButtons: leftButtons, rightButtons: rightButtons)
self.toolbar = toolbar
}
}

"Done" UIBarButtonItem not displaying on number pad (Swift)

I'm trying to add a "Done" button to a text field.
The black UIToolbar is displaying, but the "Done" button is not.
In the attributes inspector, 'Return key' is set to 'Done' and 'Auto-enable Return Key' is enabled.
The UITextField is connected to the delegate
This is inside a UITableViewCell:
import UIKit
class itemTableViewCell: UITableViewCell, UITextFieldDelegate {
#IBOutlet var itemName: UILabel!
#IBOutlet var itemInput: UITextField!
var textFieldIsBeingEdited: Bool = false
override func awakeFromNib() {
super.awakeFromNib()
itemInput.delegate = self
self.addDoneButtonToKeyboard()
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func addDoneButtonToKeyboard(){
let doneToolbar: UIToolbar = UIToolbar(frame: CGRectMake(0, 0, 320, 50))
doneToolbar.barStyle = UIBarStyle.BlackTranslucent
let flexSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)
let done: UIBarButtonItem = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Done, target: itemInput, action: Selector("doneButtonAction"))
let items = NSMutableArray()
items.addObject(flexSpace)
items.addObject(done)
doneToolbar.sizeToFit()
itemInput.inputAccessoryView = doneToolbar
}
func doneButtonAction()
{
self.itemInput.resignFirstResponder()
}
func textFieldShouldReturn(textField: UITextField!) -> Bool {
textField.resignFirstResponder()
return true
}
}
you forget to add the items to your let doneToolbar: UIToolbar
doneToolbar.items = items as [AnyObject]
brief answer
items.addObject(flexSpace)
items.addObject(done)
doneToolbar.items = items as [AnyObject]
doneToolbar.sizeToFit()
itemInput.inputAccessoryView = doneToolbar

Why does my code not add a tool bar and a done button to my keyboards?

I followed a tutorial online to add a custom toolbar and a done button to a keyboard. Xcode does not give me any errors, but when I run my app, there is no toolbar or done button an my keyboard. What did I do wrong in my code? Thanks!
Here is my code-
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var textField: UITextField!
override func viewDidLoad()
{
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
let keyboardDoneButtonShow = UIToolbar(frame: CGRectMake(200,200, self.view.frame.size.width,30))
keyboardDoneButtonShow.barStyle = UIBarStyle .BlackTranslucent
let button: UIButton = UIButton()
button.frame = CGRectMake(0, 0, 65, 20)
button.setTitle("Done", forState: UIControlState .Normal)
button.addTarget(self, action: Selector("textFieldShouldReturn:"), forControlEvents: UIControlEvents .TouchUpInside)
button.backgroundColor = UIColor .clearColor()
let doneButton: UIBarButtonItem = UIBarButtonItem()
doneButton.customView = button
let negativeSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FixedSpace, target: nil, action: nil)
negativeSpace.width = -10.0
let flexSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)
let toolbarButton = [flexSpace,doneButton,negativeSpace]
keyboardDoneButtonShow.setItems(toolbarButton, animated: false)
textField.inputAccessoryView = keyboardDoneButtonShow
return true
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
self.view.endEditing(true)
return false
}
}
Here is my result-
I think you have not set your TextField's delegate to your View Controller. In viewDidLoad add the following:
self.textField.delegate = self

Resources