From acb20fc10adf0412738bc626e92e372d565d6678 Mon Sep 17 00:00:00 2001
From: Lorenzo Pichilli <pichillilorenzo@gmail.com>
Date: Tue, 14 Nov 2023 22:47:54 +0100
Subject: [PATCH] fix #1837

---
 CHANGELOG.md                                     |  1 +
 example/lib/headless_in_app_webview.screen.dart  |  4 +++-
 .../HeadlessInAppWebView.swift                   |  1 +
 .../InAppBrowserWebViewController.swift          |  1 +
 .../InAppWebView/FlutterWebViewController.swift  | 16 ++++++++++++++--
 ios/Classes/InAppWebView/InAppWebView.swift      |  1 -
 .../InAppWebView/InAppWebViewManager.swift       |  2 +-
 .../HeadlessInAppWebView.swift                   |  4 +---
 .../InAppBrowserWebViewController.swift          |  1 +
 .../InAppWebView/FlutterWebViewController.swift  | 14 +++++++++++++-
 macos/Classes/InAppWebView/InAppWebView.swift    |  1 -
 .../InAppWebView/InAppWebViewManager.swift       |  2 +-
 12 files changed, 37 insertions(+), 11 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9db221b8..ca6640a6 100755
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,7 @@
 - Added `disableWebView` static method on `InAppWebViewController` for Android
 - Added support for Android `WebViewFeature.isStartupFeatureSupported`, `WebViewFeature.STARTUP_FEATURE_SET_DIRECTORY_BASE_PATHS`, `WebViewFeature.STARTUP_FEATURE_SET_DATA_DIRECTORY_SUFFIX`, `WebViewFeature.WEB_MESSAGE_ARRAY_BUFFER`
 - Added `WebMessage.type` property
+- Fixed "iOS EXC_BAD_ACCESS crash on kill app with InAppWebView keyboard open" [#1837](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1837)
 
 ### BREAKING CHANGES
 
diff --git a/example/lib/headless_in_app_webview.screen.dart b/example/lib/headless_in_app_webview.screen.dart
index 6df4fd25..34e5bf38 100755
--- a/example/lib/headless_in_app_webview.screen.dart
+++ b/example/lib/headless_in_app_webview.screen.dart
@@ -25,7 +25,9 @@ class _HeadlessInAppWebViewExampleScreenState
 
     headlessWebView = new HeadlessInAppWebView(
       initialUrlRequest: URLRequest(url: url),
-      initialSettings: InAppWebViewSettings(),
+      initialSettings: InAppWebViewSettings(
+        isInspectable: kDebugMode,
+      ),
       onWebViewCreated: (controller) {
         print('HeadlessInAppWebView created!');
       },
diff --git a/ios/Classes/HeadlessInAppWebView/HeadlessInAppWebView.swift b/ios/Classes/HeadlessInAppWebView/HeadlessInAppWebView.swift
index 3cb5262f..e7f035c9 100644
--- a/ios/Classes/HeadlessInAppWebView/HeadlessInAppWebView.swift
+++ b/ios/Classes/HeadlessInAppWebView/HeadlessInAppWebView.swift
@@ -80,6 +80,7 @@ public class HeadlessInAppWebView : Disposable {
         channelDelegate?.dispose()
         channelDelegate = nil
         plugin?.headlessInAppWebViewManager?.webViews[id] = nil
+        flutterWebView?.dispose(removeFromSuperview: true)
         flutterWebView = nil
         plugin = nil
     }
diff --git a/ios/Classes/InAppBrowser/InAppBrowserWebViewController.swift b/ios/Classes/InAppBrowser/InAppBrowserWebViewController.swift
index f96f9053..6f01c4e3 100755
--- a/ios/Classes/InAppBrowser/InAppBrowserWebViewController.swift
+++ b/ios/Classes/InAppBrowser/InAppBrowserWebViewController.swift
@@ -630,6 +630,7 @@ public class InAppBrowserWebViewController: UIViewController, InAppBrowserDelega
         channelDelegate?.dispose()
         channelDelegate = nil
         webView?.dispose()
+        webView?.removeFromSuperview()
         webView = nil
         view = nil
         if previousStatusBarStyle != -1 {
diff --git a/ios/Classes/InAppWebView/FlutterWebViewController.swift b/ios/Classes/InAppWebView/FlutterWebViewController.swift
index 5eda9f19..1772b5bc 100755
--- a/ios/Classes/InAppWebView/FlutterWebViewController.swift
+++ b/ios/Classes/InAppWebView/FlutterWebViewController.swift
@@ -9,7 +9,7 @@ import Foundation
 import WebKit
 
 public class FlutterWebViewController: NSObject, FlutterPlatformView, Disposable {
-    
+
     var myView: UIView?
     var keepAliveId: String?
 
@@ -185,15 +185,27 @@ public class FlutterWebViewController: NSObject, FlutterPlatformView, Disposable
         }
     }
     
-    public func dispose() {
+    // method added to fix:
+    // https://github.com/pichillilorenzo/flutter_inappwebview/issues/1837
+    public func dispose(removeFromSuperview: Bool) {
         if keepAliveId == nil {
             if let webView = webView() {
                 webView.dispose()
+                if removeFromSuperview {
+                    webView.removeFromSuperview()
+                }
+            }
+            if removeFromSuperview {
+                myView?.removeFromSuperview()
             }
             myView = nil
         }
     }
     
+    public func dispose() {
+        dispose(removeFromSuperview: false)
+    }
+    
     deinit {
         debugPrint("FlutterWebViewController - dealloc")
         dispose()
diff --git a/ios/Classes/InAppWebView/InAppWebView.swift b/ios/Classes/InAppWebView/InAppWebView.swift
index bc27b20d..701a3f41 100755
--- a/ios/Classes/InAppWebView/InAppWebView.swift
+++ b/ios/Classes/InAppWebView/InAppWebView.swift
@@ -3300,7 +3300,6 @@ if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) {
         isPausedTimersCompletionHandler = nil
         SharedLastTouchPointTimestamp.removeValue(forKey: self)
         callAsyncJavaScriptBelowIOS14Results.removeAll()
-        super.removeFromSuperview()
         plugin = nil
     }
     
diff --git a/ios/Classes/InAppWebView/InAppWebViewManager.swift b/ios/Classes/InAppWebView/InAppWebViewManager.swift
index 19d42f92..b88e6b5e 100755
--- a/ios/Classes/InAppWebView/InAppWebViewManager.swift
+++ b/ios/Classes/InAppWebView/InAppWebViewManager.swift
@@ -79,7 +79,7 @@ public class InAppWebViewManager: ChannelDelegate {
     public func disposeKeepAlive(keepAliveId: String) {
         if let flutterWebView = keepAliveWebViews[keepAliveId] as? FlutterWebViewController {
             flutterWebView.keepAliveId = nil
-            flutterWebView.dispose()
+            flutterWebView.dispose(removeFromSuperview: true)
             keepAliveWebViews[keepAliveId] = nil
         }
     }
diff --git a/macos/Classes/HeadlessInAppWebView/HeadlessInAppWebView.swift b/macos/Classes/HeadlessInAppWebView/HeadlessInAppWebView.swift
index ee109a64..e32fbcda 100644
--- a/macos/Classes/HeadlessInAppWebView/HeadlessInAppWebView.swift
+++ b/macos/Classes/HeadlessInAppWebView/HeadlessInAppWebView.swift
@@ -82,9 +82,7 @@ public class HeadlessInAppWebView : Disposable {
         channelDelegate?.dispose()
         channelDelegate = nil
         plugin?.headlessInAppWebViewManager?.webViews[id] = nil
-        if let view = flutterWebView?.view() {
-            view.superview?.removeFromSuperview()
-        }
+        flutterWebView?.dispose(removeFromSuperview: true)
         flutterWebView = nil
         plugin = nil
     }
diff --git a/macos/Classes/InAppBrowser/InAppBrowserWebViewController.swift b/macos/Classes/InAppBrowser/InAppBrowserWebViewController.swift
index 5ab6a9af..4daaaabe 100755
--- a/macos/Classes/InAppBrowser/InAppBrowserWebViewController.swift
+++ b/macos/Classes/InAppBrowser/InAppBrowserWebViewController.swift
@@ -326,6 +326,7 @@ public class InAppBrowserWebViewController: NSViewController, InAppBrowserDelega
         channelDelegate?.dispose()
         channelDelegate = nil
         webView?.dispose()
+        webView?.removeFromSuperview()
         webView = nil
         window = nil
         plugin = nil
diff --git a/macos/Classes/InAppWebView/FlutterWebViewController.swift b/macos/Classes/InAppWebView/FlutterWebViewController.swift
index df77762c..3e8e85c8 100755
--- a/macos/Classes/InAppWebView/FlutterWebViewController.swift
+++ b/macos/Classes/InAppWebView/FlutterWebViewController.swift
@@ -174,15 +174,27 @@ public class FlutterWebViewController: NSObject, /*FlutterPlatformView,*/ Dispos
         }
     }
     
-    public func dispose() {
+    // method added to fix:
+    // https://github.com/pichillilorenzo/flutter_inappwebview/issues/1837
+    public func dispose(removeFromSuperview: Bool) {
         if keepAliveId == nil {
             if let webView = webView() {
                 webView.dispose()
+                if removeFromSuperview {
+                    webView.removeFromSuperview()
+                }
+            }
+            if removeFromSuperview {
+                myView?.removeFromSuperview()
             }
             myView = nil
         }
     }
     
+    public func dispose() {
+        dispose(removeFromSuperview: false)
+    }
+    
     deinit {
         debugPrint("FlutterWebViewController - dealloc")
         dispose()
diff --git a/macos/Classes/InAppWebView/InAppWebView.swift b/macos/Classes/InAppWebView/InAppWebView.swift
index a2de17f0..393417a3 100755
--- a/macos/Classes/InAppWebView/InAppWebView.swift
+++ b/macos/Classes/InAppWebView/InAppWebView.swift
@@ -2626,7 +2626,6 @@ if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) {
         navigationDelegate = nil
         isPausedTimersCompletionHandler = nil
         callAsyncJavaScriptBelowIOS14Results.removeAll()
-        super.removeFromSuperview()
         plugin = nil
     }
     
diff --git a/macos/Classes/InAppWebView/InAppWebViewManager.swift b/macos/Classes/InAppWebView/InAppWebViewManager.swift
index 19486446..692ba193 100755
--- a/macos/Classes/InAppWebView/InAppWebViewManager.swift
+++ b/macos/Classes/InAppWebView/InAppWebViewManager.swift
@@ -80,7 +80,7 @@ public class InAppWebViewManager: ChannelDelegate {
     public func disposeKeepAlive(keepAliveId: String) {
         if let flutterWebView = keepAliveWebViews[keepAliveId] as? FlutterWebViewController {
             flutterWebView.keepAliveId = nil
-            flutterWebView.dispose()
+            flutterWebView.dispose(removeFromSuperview: true)
             keepAliveWebViews[keepAliveId] = nil
         }
     }