Skip to main content

Overview

The Resign subspec enables “tap-to-dismiss” functionality, allowing users to dismiss the keyboard by tapping anywhere outside of the active text field. This provides an intuitive way to close the keyboard without requiring a Done button.

Installation

CocoaPods

Podfile
# Include as part of IQKeyboardManagerSwift
pod 'IQKeyboardManagerSwift'

# Or include the specific subspec
pod 'IQKeyboardManagerSwift/Resign'

Swift Package Manager

The Resign functionality is included in the main package:
https://github.com/hackiftekhar/IQKeyboardManager.git

Basic Setup

1

Import the library

AppDelegate.swift
import IQKeyboardManagerSwift
2

Enable resign on touch outside

AppDelegate.swift
func application(_ application: UIApplication,
                 didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    
    // Enable keyboard management
    IQKeyboardManager.shared.isEnabled = true
    
    // Enable tap-to-dismiss
    IQKeyboardManager.shared.resignOnTouchOutside = true
    
    return true
}
3

Test tap-to-dismiss

Run your app, tap on a text field to show the keyboard, then tap anywhere outside the text field to dismiss it.

How It Works

When enabled, IQKeyboardManager:
  1. Adds a tap gesture recognizer to the window
  2. Detects taps outside active text fields
  3. Dismisses the keyboard when a tap is detected
  4. Ignores taps on interactive controls (buttons, switches, etc.)
  5. Handles conflicts with existing gestures

Configuration

Enable/Disable

// Enable tap-to-dismiss
IQKeyboardManager.shared.resignOnTouchOutside = true

// Disable tap-to-dismiss
IQKeyboardManager.shared.resignOnTouchOutside = false

Programmatic Dismissal

Manually dismiss the keyboard:
ViewController.swift
import IQKeyboardManagerSwift

class FormViewController: UIViewController {
    
    @IBAction func submitForm(_ sender: UIButton) {
        // Dismiss keyboard before processing
        IQKeyboardManager.shared.resignFirstResponder()
        
        // Process form
        processFormData()
    }
    
    @IBAction func cancelForm(_ sender: UIButton) {
        // Alternative way to dismiss
        view.endEditing(true)
    }
    
    func processFormData() {
        // Handle form submission
    }
}

Class-Level Control

Disable for Specific View Controllers

Prevent tap-to-dismiss for specific view controllers:
AppDelegate.swift
// Enable globally
IQKeyboardManager.shared.resignOnTouchOutside = true

// Disable for specific view controllers
IQKeyboardManager.shared.disabledTouchResignedClasses = [
    ChatViewController.self,
    SearchViewController.self
]
By default, UIAlertController and UIInputViewController are in the disabled list.

Force Enable for Specific Classes

AppDelegate.swift
IQKeyboardManager.shared.enabledTouchResignedClasses = [
    CustomFormViewController.self,
    ProfileViewController.self
]
If a class appears in both disabledTouchResignedClasses and enabledTouchResignedClasses, the disabled list takes precedence.

Ignore Specific View Types

Prevent tap-to-dismiss when tapping on specific view types:
AppDelegate.swift
// Default ignored classes: [UIControl, UINavigationBar]
IQKeyboardManager.shared.touchResignedGestureIgnoreClasses = [
    UIControl.self,
    UINavigationBar.self,
    UITableViewCell.self,
    CustomInteractiveView.self
]
By default, taps on UIControl (buttons, switches, etc.) and UINavigationBar won’t dismiss the keyboard, allowing users to interact with these elements while the keyboard is visible.

Gesture Recognizer Access

Access the tap gesture recognizer to handle conflicts:
ViewController.swift
import IQKeyboardManagerSwift

class CustomViewController: UIViewController {
    
    var customTapGesture: UITapGestureRecognizer!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Add custom tap gesture
        customTapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap))
        view.addGestureRecognizer(customTapGesture)
        
        // Handle conflicts with IQKeyboardManager
        let resignGesture = IQKeyboardManager.shared.resignGesture
        customTapGesture.require(toFail: resignGesture)
    }
    
    @objc func handleTap() {
        // Custom tap handling
    }
}

Complete Example

ViewController.swift
import UIKit
import IQKeyboardManagerSwift

class CommentViewController: UIViewController {
    
    @IBOutlet weak var commentTextView: UITextView!
    @IBOutlet weak var submitButton: UIButton!
    @IBOutlet weak var cancelButton: UIButton!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupKeyboardDismissal()
    }
    
    func setupKeyboardDismissal() {
        // Resign on touch is enabled globally
        // Tapping outside the text view will dismiss keyboard
        // Tapping buttons won't dismiss (they're UIControl)
    }
    
    @IBAction func submitComment(_ sender: UIButton) {
        // Button tap won't dismiss keyboard automatically
        // Manually dismiss before processing
        IQKeyboardManager.shared.resignFirstResponder()
        
        // Process comment
        postComment(commentTextView.text)
    }
    
    @IBAction func cancel(_ sender: UIButton) {
        // Dismiss keyboard and close view
        view.endEditing(true)
        dismiss(animated: true)
    }
    
    func postComment(_ text: String) {
        // Submit comment to server
    }
}

Advanced Scenarios

Conditional Resign

Enable resign on touch only for specific scenarios:
ViewController.swift
class DynamicFormViewController: UIViewController {
    
    var isEditMode: Bool = false {
        didSet {
            // Enable tap-to-dismiss in edit mode
            IQKeyboardManager.shared.resignOnTouchOutside = isEditMode
        }
    }
    
    @IBAction func toggleEditMode(_ sender: UIButton) {
        isEditMode.toggle()
    }
}

Per-View Controller Control

ViewController.swift
class BaseViewController: UIViewController {
    
    var shouldResignOnTouchOutside: Bool = true
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        // Configure for this view controller
        IQKeyboardManager.shared.resignOnTouchOutside = shouldResignOnTouchOutside
    }
}

class ChatViewController: BaseViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // Disable tap-to-dismiss for chat
        shouldResignOnTouchOutside = false
    }
}

class ProfileViewController: BaseViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // Enable tap-to-dismiss for profile editing
        shouldResignOnTouchOutside = true
    }
}

Custom Gesture Handling

ViewController.swift
class InteractiveViewController: UIViewController, UIGestureRecognizerDelegate {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Add custom double-tap gesture
        let doubleTap = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTap))
        doubleTap.numberOfTapsRequired = 2
        doubleTap.delegate = self
        view.addGestureRecognizer(doubleTap)
        
        // Make IQKeyboardManager's tap gesture wait for double-tap to fail
        IQKeyboardManager.shared.resignGesture.require(toFail: doubleTap)
    }
    
    @objc func handleDoubleTap() {
        print("Double tap detected")
    }
    
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,
                          shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return false
    }
}

UIScrollView Interaction

Handling tap-to-dismiss with scroll views:
ViewController.swift
class ScrollableFormViewController: UIViewController {
    
    @IBOutlet weak var scrollView: UIScrollView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Enable tap-to-dismiss
        // Taps on scroll view background will dismiss keyboard
        // Scrolling won't dismiss keyboard
        IQKeyboardManager.shared.resignOnTouchOutside = true
    }
}

Resign vs Done Button

Tap-to-Dismiss

Best for:
  • Single text field screens
  • Simple forms
  • Modal text input
  • Quick edits
Advantages:
  • Natural gesture
  • No UI required
  • Works anywhere

Done/Toolbar Button

Best for:
  • Multi-field forms
  • Guided input flows
  • Complex forms
  • Required validation
Advantages:
  • Clear action
  • More discoverable
  • Can trigger validation
You can use both tap-to-dismiss and toolbar buttons together for maximum flexibility.

Best Practices

Tap-to-dismiss is intuitive and should be enabled for most screens. Only disable it when you have specific interaction requirements.
The default configuration ignores taps on buttons and controls, which is usually what you want. Users can tap buttons without dismissing the keyboard.
If your app uses custom gestures, test thoroughly to ensure they don’t conflict with the resign gesture.
Consider adding visual feedback when the keyboard dismisses to help users understand the interaction.

Troubleshooting

  • Verify resignOnTouchOutside is set to true
  • Check if the view controller is in disabledTouchResignedClasses
  • Ensure no other gesture is blocking the tap gesture
  • Check if a custom gesture has higher priority
  • Verify UIControl is in touchResignedGestureIgnoreClasses
  • Check if button’s isUserInteractionEnabled is true
  • Ensure button is not hidden or has zero alpha
  • Use require(toFail:) to manage gesture priority
  • Implement UIGestureRecognizerDelegate for custom control
  • Access IQKeyboardManager.shared.resignGesture to handle conflicts
  • Add UITableViewCell to touchResignedGestureIgnoreClasses
  • Or implement tableView(_:didSelectRowAt:) to dismiss manually
resignOnTouchOutside
Bool
default:"false"
Enable tap-to-dismiss keyboard functionality
resignGesture
UITapGestureRecognizer
default:"UITapGestureRecognizer()"
The tap gesture recognizer used for dismiss functionality. Read-only, exposed for handling gesture dependencies.
disabledTouchResignedClasses
[UIViewController.Type]
View controller classes where tap-to-dismiss is disabled
enabledTouchResignedClasses
[UIViewController.Type]
default:"[]"
View controller classes where tap-to-dismiss is force-enabled
touchResignedGestureIgnoreClasses
[UIView.Type]
default:"[UIControl.self, UINavigationBar.self]"
View classes that won’t trigger tap-to-dismiss when tapped

Next Steps

Advanced Configuration

Fine-tune keyboard behavior

Toolbar Management

Add navigation buttons to keyboard

Debugging

Troubleshoot resign issues

API Reference

Full API documentation

Build docs developers (and LLMs) love