diff --git a/src/plugins/platforms/ios/qiosinputcontext.h b/src/plugins/platforms/ios/qiosinputcontext.h
index f07408db81d127fe5f4f873d23da332d50c5eafa..1f1130f932d123948ca9d258898c856888f117b1 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.h
+++ b/src/plugins/platforms/ios/qiosinputcontext.h
@@ -51,9 +51,10 @@ QT_BEGIN_NAMESPACE
 
 struct ImeState
 {
-    ImeState() : currentState(0) {}
+    ImeState() : currentState(0), focusObject(0) {}
     Qt::InputMethodQueries update(Qt::InputMethodQueries properties);
     QInputMethodQueryEvent currentState;
+    QObject *focusObject;
 };
 
 class QIOSInputContext : public QPlatformInputContext
diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm
index acdf6d9715c9e284807ef00f5b20407d38669d2f..072a49c7c57cf741726380fb105828ecc1f25fcc 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.mm
+++ b/src/plugins/platforms/ios/qiosinputcontext.mm
@@ -300,8 +300,11 @@ Qt::InputMethodQueries ImeState::update(Qt::InputMethodQueries properties)
 
     QInputMethodQueryEvent newState(properties);
 
-    if (qApp && qApp->focusObject())
-        QCoreApplication::sendEvent(qApp->focusObject(), &newState);
+    // Update the focus object that the new state is based on
+    focusObject = qApp ? qApp->focusObject() : 0;
+
+    if (focusObject)
+        QCoreApplication::sendEvent(focusObject, &newState);
 
     Qt::InputMethodQueries updatedProperties;
     for (uint i = 0; i < (sizeof(Qt::ImQueryAll) * CHAR_BIT); ++i) {
@@ -348,11 +351,23 @@ QRectF QIOSInputContext::keyboardRect() const
 void QIOSInputContext::showInputPanel()
 {
     // No-op, keyboard controlled fully by platform based on focus
+    qImDebug() << "can't show virtual keyboard without a focus object, ignoring";
 }
 
 void QIOSInputContext::hideInputPanel()
 {
-    // No-op, keyboard controlled fully by platform based on focus
+    if (![m_textResponder isFirstResponder]) {
+        qImDebug() << "QIOSTextInputResponder is not first responder, ignoring";
+        return;
+    }
+
+    if (qGuiApp->focusObject() != m_imeState.focusObject) {
+        qImDebug() << "current focus object does not match IM state, likely hiding from focusOut event, so ignoring";
+        return;
+    }
+
+    qImDebug() << "hiding VKB as requested by QInputMethod::hide()";
+    [m_textResponder resignFirstResponder];
 }
 
 void QIOSInputContext::clearCurrentFocusObject()