Swift:
The next solution is for UITextView, but you can modify it for UITextField
1) Add keyboardWillShow event handler in the view controller that contains the field and save a reference to the field
/**
Listen keyboard events
:param: animated the animation flag
*/
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
initNavigation()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
}
/**
Remove self as keyboard listener
:param: animated the animation flag
*/
override func viewWillDisappear(animated: Bool) {
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}
/**
Save reference to focused textView
:param: sender the sender
*/
func keyboardWillShow(sender: AnyObject){
if self.searchTextField?.isFirstResponder() ?? false {
KeyboardDismissingUIViewTarget = self.searchTextField
}
}
/**
Clean KeyboardDismissingUIViewTarget
:param: sender the sender
*/
func keyboardWillHide(sender: AnyObject){
KeyboardDismissingUIViewTarget = nil
}
2) Use custom class for top most UIView:
/// the target view (textView) which should not dismiss the keyboard
var KeyboardDismissingUIViewTarget: UIView?
/**
* Custom class for top view that dismisses keyboard when tapped outside the given textView or textField
*
* @author Alexander Volkov
* @version 1.0
*/
class KeyboardDismissingUIView: UIView {
override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
if let targetView = KeyboardDismissingUIViewTarget as? UITextView {
// Convert the point to the target view's coordinate system.
// The target view isn't necessarily the immediate subview
let pointForTargetView = targetView.convertPoint(point, fromView: self)
if CGRectContainsPoint(targetView.bounds, pointForTargetView) {
return targetView.hitTest(pointForTargetView, withEvent: event)
}
else {
KeyboardDismissingUIViewTarget = nil
targetView.resignFirstResponder()
return nil
}
}
return super.hitTest(point, withEvent: event)
}
}