World’s largest virtual agentic engineering & quality conference

WHENAUG 19-21
WHEREVirtual · Global
Register Now
Mobile App TestingTutorial

IQKeyboardManager in Swift: Setup, the v8 isEnabled Rename, and Device Testing

IQKeyboardManager v8 declares isEnabled as false while its doc comment says YES. The enable rename, keyboardDistance defaults, and testing on real iOS devices.

Author

Sai Krishna

Author

Author

Shivam Singh

Reviewer

Last Updated on: August 7, 2026

Overview

IQKeyboardManager is an MIT-licensed UIKit library that stops the iOS keyboard covering a UITextField or UITextView. Version 8.0.3 requires iOS 13 or later and needs one line: set IQKeyboardManager.shared.isEnabled to true. That property was called enable before version 8.0.0, which is why so much published sample code no longer compiles.

What Changed in Version 8?

  • isEnabled: The activation flag, renamed from enable in version 8.0.0. No deprecation shim exists for the old spelling, so an upgrade fails with a plain has-no-member error rather than a rename suggestion.
  • keyboardDistance: The gap held between the keyboard and the focused field, defaulting to 10.0 points. Its version 7 name, keyboardDistanceFromTextField, is marked unavailable and will not build.
  • enableAutoToolbar: Still present, but now defaults to false because the Previous, Next and Done bar moved into a separate IQKeyboardToolbarManager package. This is why the toolbar vanishes after upgrading.
  • SwiftUI support: Absent by design. The maintainer declined it in 2023 because SwiftUI already handles keyboard avoidance through its safe area, and the toolbar arrows cannot work in a SwiftUI view hierarchy.
  • Whether the fix actually holds depends on screen height and safe-area insets, so a layout that passes on a large iPhone can still clip the submit button on a compact one. TestMu AI runs the same build across real iPhone and iPad models to catch that.

Should You Use It on a New App?

On SwiftUI, no. On UIKit targeting iOS 15 or later, Apple's keyboardLayoutGuide covers plain avoidance in one constraint. IQKeyboardManager still earns its place below iOS 15 and when you want the accessory toolbar and return-key chaining.

You add the pod, paste the one line every tutorial shows, build, tap the bottom text field, and the keyboard still sits on top of it. Nothing in the console, no crash, no warning. The setup looked like a two-minute job and now it is an afternoon.

That experience is common enough to have its own Stack Overflow question, titled IQKeyboardManager Swift Does Not Work At All. The usual cause is a property rename that most of the guidance still in circulation predates, compounded by a default value that does not match the library's own documentation.

What Is IQKeyboardManager?

IQKeyboardManager is an open source UIKit library that stops the iOS software keyboard from covering a UITextField or UITextView. When a field gains focus it shifts the view hierarchy so the field stays visible, then restores the original position once the keyboard dismisses. It is MIT licensed and requires iOS 13 or later.

UIKit does not move your layout when the software keyboard appears. The keyboard is drawn over the window, and any control sitting in the lower part of the screen is simply covered. Handling that yourself means observing keyboard notifications, reading the frame out of the notification payload, and adjusting constraints or scroll insets by hand.

IQKeyboardManager does that work globally, without per-screen code. The IQKeyboardManager repository is MIT licensed and carries more than 16,000 GitHub stars. Its four headline behaviors are:

  • Automatic avoidance for UITextField and UITextView, including fields nested in UIScrollView, UITableView and UICollectionView.
  • An optional accessory toolbar carrying Previous, Next and Done controls above the keyboard.
  • Return-key chaining, so the return key advances focus to the next field instead of dismissing.
  • Tap-outside-to-resign, dismissing the keyboard when the user taps away from the field. Like isEnabled, this is off until you set resignOnTouchOutside to true.

One caveat is worth reading before you adopt it. The README states plainly that if you are building an SDK, library or framework, adding IQKeyboardManager as a shipped dependency is the wrong approach. Its behavior is global by design, so bundling it into a library would impose that behavior on every host app.

Requirements and Installation

The podspec for 8.0.3 declares a minimum platform of iOS 13.0 and Swift versions 5.7, 5.8 and 5.9. The README's requirements table adds a floor of Xcode 13, with Xcode 15 needed only to open the bundled demo project. Ignore the requirements table rendered on the CocoaPods listing page: it still shows iOS 8.0 and Xcode 9, which is version 6 era text that was never refreshed.

MethodWhat to writeStatus
Swift Package ManagerAdd github.com/hackiftekhar/IQKeyboardManager.git via File then Add Package DependencyRecommended. Vends one library product, IQKeyboardManagerSwift.
CocoaPodspod 'IQKeyboardManagerSwift'Supported. The listing page suggests pinning to ~> 8.0.
Carthagegithub "hackiftekhar/IQKeyboardManager", built with --use-xcframeworksStill documented in the README.
Manual source drop-inCopying the source folder into your projectNot supported since 7.2.0. The library now depends on separate packages, so this produces compilation errors.

Version 8 restructured the project into several independent repositories that the main package depends on, among them IQKeyboardNotification, IQTextInputViewNotification, IQKeyboardToolbarManager and IQKeyboardReturnManager. Swift Package Manager still exposes a single product, so one package dependency pulls them all in. Those sibling modules are not re-exported, though, so referencing one directly needs its own import line. CocoaPods surfaces the same split as six subspecs, all installed by default. That restructuring is what killed manual installation.

If you are new to dependency management in an iOS project, the mechanics of adding a package and resolving it live in Xcode, and the workflow is the same regardless of which manager you pick.

The Minimal Setup

Two lines total: one import, one assignment in your app delegate. This is the current version 8 form.

import UIKit
import IQKeyboardManagerSwift

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        // Version 8: the property is isEnabled, not enable
        IQKeyboardManager.shared.isEnabled = true

        return true
    }
}

That is the whole integration. No subclassing, no per-view-controller wiring, and no keyboard notification observers of your own. The library runs its own app-wide keyboard and text-input observers, covering every UITextField and UITextView you present.

Why Is IQKeyboardManager Not Working?

IQKeyboardManager is usually not working because isEnabled was never set to true. Version 8 declares the property as public var isEnabled: Bool = false, so the library stays inert until you assign it, despite a doc comment directly above the declaration still claiming the default is YES. Nothing is logged when this happens.

The library markets itself as codeless. The repository description still says you need neither write any code nor do any setup. Both statements are misleading in version 8, and the reason is visible in the shipping source. Pulling the two relevant files straight from the master branch shows it:

$ curl -sL https://raw.githubusercontent.com/hackiftekhar/IQKeyboardManager/master/\
    IQKeyboardManagerSwift/IQKeyboardManager/IQKeyboardManager.swift | grep -n -B4 "var isEnabled"

68-    /**
69-    Enable/disable managing distance between keyboard and textInputView.
70-     Default is YES(Enabled when class loads in `+(void)load` method).
71-    */
72:    public var isEnabled: Bool = false {

The doc comment on line 70 says the default is YES. The declaration on line 72 sets it to false. The comment is a leftover from the Objective-C implementation, where the class did enable itself in a load method. In the Swift package it does not, so the library sits inert until you assign true. Nothing logs a warning, which is exactly why the failure is so hard to diagnose.

There is a second cause that produces the same symptom on a screen-by-screen basis. The property disabledDistanceHandlingClasses ships with UITableViewController, UIInputViewController and UIAlertController already in it. If your form lives inside a UITableViewController, distance handling is off by default and the library will appear broken on that screen while working everywhere else.

Work through these in order before assuming the library is at fault:

  • Confirm you set isEnabled to true, not enable, and that the assignment runs in didFinishLaunchingWithOptions.
  • Confirm the import is IQKeyboardManagerSwift. Installing the legacy Objective-C pod named IQKeyboardManager while importing the Swift module is a common mix-up, and the CocoaPods trunk listing shows that pod last shipped 6.5.19 in May 2024 while the Swift line moved on to 8.x.
  • Check whether the failing screen is a UITableViewController, which is excluded from distance handling by default.
  • If only the toolbar is missing, that is the version 8 default change covered below rather than an install problem.

One more behavior gets reported as a bug. If you see a slightly larger gap than you configured, the library is deliberately adding the safe-area bottom inset, because moving the root view frame zeroes that margin and the field would otherwise sit partly behind the keyboard. The maintainer notes this generally does not occur when the field is inside a scroll view.

Note

Note: Keyboard occlusion depends on screen height and safe-area insets, so the same build behaves differently on an iPhone SE and an iPad Pro. TestMu AI lets you run your app across real iOS hardware instead of guessing from one simulator. Try it free

IQKeyboardManager enable vs isEnabled: What Changed in Version 8

IQKeyboardManager.shared.enable became IQKeyboardManager.shared.isEnabled in version 8.0.0, tagged 4 November 2024. No deprecation shim exists for the old spelling, so the compiler reports only that IQKeyboardManager has no member named enable, without naming a replacement. Seven further properties were renamed in the same release.

// Version 6 and 7. Does not compile on version 8.
IQKeyboardManager.sharedManager().enable = true
IQKeyboardManager.shared.enable = true

// Version 8
IQKeyboardManager.shared.isEnabled = true

Version 8.0.0 was tagged on 4 November 2024 and renamed a large part of the public surface. Note that the release dates shown on the GitHub releases page are not reliable for this project: the newest twenty-seven entries were all back-filled on 25 May 2026 within about half an hour, so the annotated tag dates are the real ship dates.

Most renamed properties carry an unavailable attribute, which gives you a compiler error naming the replacement. Two do not, and those are the ones that waste an afternoon.

Version 6 or 7 nameVersion 8 replacementWhat the compiler tells you
sharedManager()sharedNothing useful. The accessor became a static property back in 6.0 with no shim, so the build stops here before it ever reaches the flag.
enableisEnabledNothing useful. No shim exists, so you get a bare has-no-member error.
enableDebuggingisDebuggingEnabledNothing useful. No shim exists here either.
keyboardDistanceFromTextFieldkeyboardDistanceMarked unavailable, renamed to keyboardDistance.
overrideKeyboardAppearancekeyboardConfiguration.overrideAppearanceMarked unavailable, with the replacement path named.
keyboardAppearancekeyboardConfiguration.appearanceMarked unavailable, with the replacement path named.
toolbarTintColortoolbarConfiguration.tintColorMarked unavailable, with the replacement path named.
toolbarDoneBarButtonItemTexttoolbarConfiguration.doneBarButtonConfiguration.titleMarked unavailable, with the replacement path named.
enableAutoToolbarDeprecated. It now forwards to IQKeyboardToolbarManager.shared.isEnabled, which defaults to false.A deprecation warning naming IQKeyboardToolbarManager. Ignore it and the toolbar simply stops appearing.

Migrating from version 5 or from an Objective-C codebase changes both halves of the activation line at once: IQKeyboardManager.sharedManager().enable = true becomes IQKeyboardManager.shared.isEnabled = true. Because neither name carries a rename attribute, the compiler surfaces only the sharedManager error on the first build and stays silent about enable until you have fixed the accessor, which is why this reads as two unrelated failures.

Version 7 had already moved the per-field API onto an iq namespace, so a per-field distance override is now written as textField.iq.distanceFromKeyboard. Left at its sentinel default, that property falls back to the global keyboardDistance value.

There is one trap in the official documentation itself. The README's appearance example uses keyboardConfiguration.overrideKeyboardAppearance and keyboardConfiguration.keyboardAppearance, but the IQKeyboardAppearanceConfiguration class declares those properties as overrideAppearance and appearance, and the deprecation attributes point at the shorter names too. The README snippet does not compile. Follow the table above rather than that example.

IQKeyboardManager Properties and Their Defaults

Every default below is read from the shipping version 8 source, not from the doc comments, because on at least one property the two disagree. This is the reference the library's own documentation does not currently provide accurately.

PropertyTypeDefault in v8What it does
isEnabledBoolfalseMaster switch for distance handling. Nothing happens until you set it, despite the doc comment above it claiming the default is YES.
keyboardDistanceCGFloat10.0Points held between the keyboard and the focused field. Override per field with textField.iq.distanceFromKeyboard.
resignOnTouchOutsideBoolfalseDismisses the keyboard when the user taps away from the field.
layoutIfNeededOnUpdateBoolfalseCalls setNeedsLayout and layoutIfNeeded on any frame update of the view controller's view.
enableAutoToolbarBoolfalseDeprecated. Forwards to IQKeyboardToolbarManager.shared.isEnabled, which also defaults to false.
isDebuggingEnabledBoolfalsePrints the library's decisions to the console. Renamed from enableDebugging in version 8 with no shim.
disabledDistanceHandlingClasses[UIViewController.Type]UITableViewController, UIInputViewController, UIAlertControllerScreens excluded from distance handling. Preloaded, so it is not empty.
enabledDistanceHandlingClasses[UIViewController.Type]emptyScreens forced back on. Ignored for any class already in the disabled list.

Two of these carry almost no coverage anywhere online, and both are worth knowing before you conclude the library is misbehaving.

resignOnTouchOutside

Tap-outside-to-dismiss is off until you turn it on, which catches people who expect it as part of the default install. In version 7 this property was called shouldResignOnTouchOutside; the old name now carries an unavailable attribute that names the replacement, so at least the compiler tells you what to write. Exclude individual screens with disabledTouchResignedClasses.

layoutIfNeededOnUpdate

This one was not renamed and is easy to miss. Turning it on makes the library call setNeedsLayout and layoutIfNeeded on every frame update of the view controller's view, which is what you want when constraint-driven subviews lag behind the shift and arrive a frame late. Leave it off unless you can see that lag.

How to Change the Keyboard Distance in IQKeyboardManager

Set IQKeyboardManager.shared.keyboardDistance to change the gap between the keyboard and the focused field. It defaults to 10.0 points in version 8. The version 7 name keyboardDistanceFromTextField is marked unavailable and will not compile. To change one field rather than the whole app, set textField.iq.distanceFromKeyboard instead.

The defaults are conservative. This is the version 8 form of the configuration most apps end up writing, with the toolbar switched back on explicitly.

import IQKeyboardManagerSwift
import IQKeyboardToolbarManager

// IQKeyboardManager is @MainActor isolated, so this must be too.
@MainActor
func configureKeyboardHandling() {

    let manager = IQKeyboardManager.shared

    manager.isEnabled = true

    // Gap between the keyboard and the focused field. Source default is 10.0 points.
    manager.keyboardDistance = 24

    // Tap outside a field to dismiss it. Also defaults to false.
    manager.resignOnTouchOutside = true

    // Dark keyboard everywhere. Note: overrideAppearance, not overrideKeyboardAppearance.
    manager.keyboardConfiguration.overrideAppearance = true
    manager.keyboardConfiguration.appearance = .dark

    // The Previous / Next / Done bar defaults to false in version 8. Set it on the
    // toolbar manager directly; IQKeyboardManager.enableAutoToolbar is deprecated.
    IQKeyboardToolbarManager.shared.isEnabled = true
}

Be careful reading the README on distance. Its example sets keyboardDistance to 20.0, which is easy to mistake for the default. The source declares the default as 10.0 points.

The wiki page listing properties and functions is worth skipping entirely. It still documents the Objective-C sharedManager accessor alongside enable and keyboardDistanceFromTextField, none of which reflect the shipping Swift API.

How to Disable IQKeyboardManager for a View Controller

Add the view controller's class to IQKeyboardManager.shared.disabledDistanceHandlingClasses to disable IQKeyboardManager for one screen, or set textField.iq.enableMode to disabled for a single field. UITableViewController, UIInputViewController and UIAlertController already sit in that list by default, which is why forms inside a table view controller often look unmanaged.

Global behavior is the library's main appeal and its main hazard. A screen with its own scroll-adjustment logic will fight IQKeyboardManager, producing doubled offsets or a view that jumps. The fix is exclusion rather than toggling the manager on and off in view lifecycle methods, which is fragile.

let manager = IQKeyboardManager.shared

// Exclude an entire view controller from distance handling.
manager.disabledDistanceHandlingClasses.append(CheckoutViewController.self)

// Exclude a screen from tap-outside-to-resign.
manager.disabledTouchResignedClasses.append(SignatureViewController.self)

// Opt a single field out, leaving the rest of the screen managed.
otpTextField.iq.enableMode = .disabled

Remember that UITableViewController, UIInputViewController and UIAlertController are in the disabled list before you touch it. If you need the library active inside a table view controller, remove that class from the array rather than wondering why the screen behaves differently.

Run iOS + Android tests written by your AI agent.

Appium

Do You Still Need It in 2026?

IQKeyboardManager does not support SwiftUI, and on UIKit targeting iOS 15 or later Apple's keyboardLayoutGuide handles plain avoidance in a single constraint. The library still earns its place below iOS 15, since it supports iOS 13, and when you want the accessory toolbar or return-key chaining.

The platform has absorbed much of what the library was built for, and the honest answer now depends on your UI framework and deployment target.

Apple shipped keyboardLayoutGuide in iOS 15, and it is available on iOS, iPadOS, Mac Catalyst and visionOS. In the WWDC21 session introducing it, Apple showed the notification-observer approach collapsing into a single constraint against the guide's top anchor, and by WWDC23 was calling it the recommended approach, noting first-party use in Spotlight and Messages. The guide has kept gaining API since, with usesBottomSafeArea and keyboardDismissPadding arriving in iOS 17.

// Pin your lowest control above the keyboard. No notifications, no observers.
view.keyboardLayoutGuide.topAnchor.constraint(
    equalToSystemSpacingBelow: submitButton.bottomAnchor,
    multiplier: 1.0
).isActive = true

That is the whole replacement for a notification observer on a simple screen. The guide tracks the keyboard while it is up and follows the bottom safe area when it is down, so the same constraint holds in both states.

SwiftUI needs nothing at all. Apple treats the keyboard as part of the safe area and resizes views automatically, and opting out is a single ignoresSafeArea modifier. The library's maintainer reached the same conclusion in 2023, declining SwiftUI support because SwiftUI already handles the general case, and noting the Previous and Next arrows cannot work there because SwiftUI builds a different view hierarchy.

Your situationWhat to reach for
SwiftUI, any versionBuilt-in avoidance. Do not add the library.
UIKit, deploying iOS 15 or later, plain avoidance onlykeyboardLayoutGuide. One constraint, no dependency.
UIKit, deploying iOS 13 or 14IQKeyboardManager. It supports iOS 13, below the guide's floor.
You want Previous / Next / Done or return-key chainingIQKeyboardManager. UIKit does not provide these.
Large legacy UIKit codebase already using itKeep it. Migrating many screens to earn one constraint is rarely worth it.

The old NotificationCenter approach has not been deprecated, and Apple's documentation for keyboardWillShowNotification carries no deprecation flag. It simply requires more careful handling, because the system does no work on your behalf.

Testing Keyboard Behavior Across Devices

Whether a field is actually visible above the keyboard is a function of screen height, safe-area insets and keyboard height, and all three vary by device. A checkout form that clears the keyboard on a large iPhone can leave the submit button clipped on a compact one. Verifying on a single simulator does not tell you much.

The simulator is also a poor proxy for the keyboard specifically. It defaults to using your Mac's hardware keyboard, so the software keyboard may never appear and your avoidance code never runs. That trap is worth understanding before you trust a green local run, and it is one of the practical differences covered in iOS Simulator setup and in the wider case for real device testing.

TestMu AI's app test automation platform runs Appium, Espresso, XCUITest and Detox suites against a cloud of 10,000+ real Android and iOS devices, so you can execute the same keyboard assertions across a spread of iPhone and iPad models in parallel rather than sequentially on the one handset in your drawer. XCUITest and Espresso run on real hardware; emulator and simulator automation currently goes through Appium. Every session returns device logs, video and screenshots, which matters here because a keyboard overlap bug is far easier to confirm from a recording than from a failed assertion message.

A practical assertion is straightforward: focus the field, wait for the keyboard, then check the field's frame still sits above the keyboard's top edge. Set the field's accessibilityIdentifier to billing_postcode in the app target first, or the query matches nothing and the test fails for the wrong reason. The XCUITest documentation covers uploading the app and test bundle to run it on the cloud grid.

import XCTest
import UIKit

final class KeyboardAvoidanceUITests: XCTestCase {

    func testFieldStaysVisibleWhenKeyboardAppears() {

        let app = XCUIApplication()
        app.launch()

        let field = app.textFields["billing_postcode"]
        field.tap()

        let keyboard = app.keyboards.element
        XCTAssertTrue(keyboard.waitForExistence(timeout: 5),
                      "Software keyboard never appeared. On a simulator, disconnect the hardware keyboard.")

        // IQKeyboardManager animates the move using the keyboard's own duration,
        // so poll until the frame settles rather than asserting immediately.
        let isClear: NSPredicate = .init { _, _ in
            field.frame.maxY <= keyboard.frame.minY
        }
        let settled: XCTNSPredicateExpectation = .init(predicate: isClear, object: nil)

        XCTAssertEqual(XCTWaiter().wait(for: [settled], timeout: 3), .completed,
                       "Field still covered by the keyboard on \(UIDevice.current.name)")
    }
}

Running that across a device matrix turns a subjective judgement into a pass or fail. You will need a build artifact to upload first, which is what an IPA file is, and the broader technique for spreading one suite over many handsets is covered in how to test iOS apps on multiple devices.

Test your website on the TestMu AI real device cloud

Getting It Right

Open your app delegate and look at the activation line. If it reads IQKeyboardManager.shared.enable = true, or IQKeyboardManager.sharedManager().enable = true, you are on version 6 or 7 syntax and that line does not compile on version 8; if the project still builds, you are pinned to an old release and should plan the rename. If it reads IQKeyboardManager.shared.isEnabled = true, the library is live and any remaining problem is a per-screen exclusion.

For new UIKit work targeting iOS 15 or later, write the keyboardLayoutGuide constraint and skip the dependency. Reach for IQKeyboardManager when you need the accessory toolbar, return-key chaining, or support below iOS 15.

Once the behavior is correct on your own device, confirm it holds on the small screens where it usually breaks. Run your XCUITest suite across a spread of real iPhone and iPad models on TestMu AI's real device cloud, and see the XCUITest tutorial if you are writing your first UI test for the framework.

Author

...

Sai Krishna

Blogs: 3

  • Linkedin

Sai Krishna is Director of Engineering at TestMu AI (formerly LambdaTest), where he leads agentic AI for quality engineering, building AI agents that autonomously drive mobile and conversational test automation. His current focus is Agent Testing and Model Context Protocol (MCP) support for mobile. He is a core contributor and member of the Appium open-source project and the creator of AppiumTestDistribution and appium-device-farm. With over 14 years of experience including more than 9 years at Thoughtworks as a Principal Consultant, he holds a BSc in Electronics and speaks regularly at TestMu and Appium Conf on Appium, mobile automation, and agentic AI in testing.

Reviewer

...

Shivam Singh

Reviewer

  • Linkedin

Shivam Singh is a Lead Member of Technical Staff at TestMu AI (formerly LambdaTest), architecting the Real Device Cloud that runs automated app and web tests on real Android and iOS devices. He designed the architecture for real-device app and web automation and wrote the microservices from scratch in Golang, including the XCUITest and Espresso execution layers for iOS and Android. His platform reached peak parallel concurrency of 150+ for app automation while handling roughly 500,000 tests a month, and he leads the team that keeps the automation grid running. He brings over eight years of engineering experience and holds a B.Tech in Computer Science.

Open in ChatGPT Icon

Open in ChatGPT

Open in Claude Icon

Open in Claude

Open in Perplexity Icon

Open in Perplexity

Open in Grok Icon

Open in Grok

Open in Gemini AI Icon

Open in Gemini AI

Copied to Clipboard!
...

3000+ Browsers. One Platform.

See exactly how your site performs everywhere.

Try it free
...

Write Tests in Plain English with KaneAI

Create, debug, and evolve tests using natural language.

Try for free
...
TestMu Conf 2026

World's largest virtual agentic engineering & quality conference

...

AUG 19-21, 2026

REGISTER NOW

IQKeyboardManager FAQs

Did you find this page helpful?

More Related Blogs

TestMu AI forEnterprise

Get access to solutions built on Enterprise
grade security, privacy, & compliance

  • Advanced access controls
  • Advanced data retention rules
  • Advanced Local Testing
  • Premium Support options
  • Early access to beta features
  • Private Slack Channel
  • Unlimited Manual Accessibility DevTools Tests