briancl briancl - 7 months ago 65
Swift Question

How do I dismiss keyboard with a touch? touchesBegan not workig

According to everything I've read here, I should override

touchesBegan()
to dismiss the keyboard (in my case DatePicker). Unfortunately touching the screen does not dismiss the DatePicker. Touching other UI elements like the UISteppers dismisses the keyboard just fine, and it is using the same function of CloseKeyboard()

class RecordWorkoutTableViewController: UITableViewController, UITextFieldDelegate {

@IBOutlet weak var dateTextField: UITextField!
@IBOutlet weak var weightLabel: UILabel!
@IBOutlet weak var setOneLabel: UILabel!
@IBOutlet weak var setTwoLabel: UILabel!
@IBOutlet weak var weightStepper: UIStepper!
@IBOutlet weak var setOneStepper: UIStepper!
@IBOutlet weak var setTwoStepper: UIStepper!

var newDate: NSDate? {
didSet {
dateTextField.text = NSDateToPrettyString(newDate!)
}
}
var newWeight: Int? {
didSet {
weightLabel.text = "\(newWeight!) lbs"
}
}

var newSetOne: Int? {
didSet {
setOneLabel.text = "Set 1: \(newSetOne!) reps"
}
}

var newSetTwo: Int? {
didSet {
setTwoLabel.text = "Set 2: \(newSetTwo!) reps"
}
}

var workout: Workout?

// MARK: UITextFieldDelegate

func textFieldDidBeginEditing(textField: UITextField) {
let datePicker = UIDatePicker()
textField.inputView = datePicker
datePicker.addTarget(self, action: #selector(RecordWorkoutTableViewController.datePickerChanged(_:)), forControlEvents: .ValueChanged)
}

func datePickerChanged(sender: UIDatePicker) {
newDate = sender.date
}

func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}

// disable editing of date text. datepicker input only
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
return false
}

// MARK: Helper Functions

func closeKeyboard() {
self.view.endEditing(true)
}

// MARK: Touch Events


override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
closeKeyboard()
}


override func viewDidLoad() {
super.viewDidLoad()
dateTextField.delegate = self

newDate = NSDate()

if let lastWorkout = workout {
newWeight = lastWorkout.sets[0].weight
newSetOne = lastWorkout.sets[0].repCount
newSetTwo = lastWorkout.sets[1].repCount
} else {
newWeight = 0
newSetOne = 9
newSetTwo = 8
}

weightStepper.stepValue = 5
weightStepper.maximumValue = 995
weightStepper.value = Double(newWeight!)

setOneStepper.stepValue = 1
setOneStepper.maximumValue = 20
setOneStepper.value = Double(newSetOne!)

setTwoStepper.stepValue = 1
setTwoStepper.maximumValue = 20
setTwoStepper.value = Double(newSetTwo!)

}

@IBAction func weightStepperChanged(sender: UIStepper) {
newWeight = Int(sender.value)
closeKeyboard()
}

@IBAction func setOneStepperChanged(sender: UIStepper) {
newSetOne = Int(sender.value)
closeKeyboard()
}

@IBAction func setTwoStepperChanged(sender: UIStepper) {
newSetTwo = Int(sender.value)
closeKeyboard()
}


}

Answer

You said in the comments that you have another class in your app named Set. Since this class is in the same module as your table view controller, Swift is prioritizing it over it's built in class.

You can fix this by either renaming your Set class, or explicitly specifying the Swift module in the function declaration:

override func touchesBegan(touches: Swift.Set<UITouch>, withEvent event: UIEvent?) {
    closeKeyboard()
}