diff --git a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md index 2f99c599beb5..5a4511008367 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md @@ -1,3 +1,8 @@ +## 3.24.1 + +* Updates platform views on iOS to only have a weak reference to the native view. This is a + potential workaround to prevent a crash during the Flutter engine shutdown. See https://github.com/flutter/flutter/issues/168535 + ## 3.24.0 * Adds support for `WebKitWebViewControllerCreationParams.javaScriptCanOpenWindowsAutomatically` to allow JavaScript's diff --git a/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/PlatformViewImplTests.swift b/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/PlatformViewImplTests.swift new file mode 100644 index 000000000000..be9a9ff1b64e --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/PlatformViewImplTests.swift @@ -0,0 +1,25 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import XCTest + +@testable import webview_flutter_wkwebview + +#if os(iOS) + import UIKit +#endif + +class PlatformViewImplTests: XCTestCase { + #if os(iOS) + func testPlatformViewImplStoresViewWithAWeakReference() { + var view: UIView? = UIView() + let platformView = PlatformViewImpl(uiView: view!) + + XCTAssertNotNil(platformView.uiView) + + view = nil + XCTAssertNil(platformView.uiView) + } + #endif +} diff --git a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/FlutterViewFactory.swift b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/FlutterViewFactory.swift index 757a329ea364..25192bab974d 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/FlutterViewFactory.swift +++ b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/FlutterViewFactory.swift @@ -13,23 +13,36 @@ import Foundation #error("Unsupported platform.") #endif -/// Implementation of `FlutterPlatformViewFactory` that retrieves the view from the `WebKitLibraryPigeonInstanceManager`. -class FlutterViewFactory: NSObject, FlutterPlatformViewFactory { - unowned let instanceManager: WebKitLibraryPigeonInstanceManager - - #if os(iOS) - class PlatformViewImpl: NSObject, FlutterPlatformView { - let uiView: UIView +#if os(iOS) + class PlatformViewImpl: NSObject, FlutterPlatformView { + // TODO(bparrishMines): Change to strong reference once this issue is fixed in the engine and + // makes it to stable. See https://github.com/flutter/flutter/issues/168535. + // The InstanceManager used by pigeon adds an associated object to added instances that makes a message call when + // they are deallocated. This sets a weak reference to the underlying UIView to prevent a crash where the UIView is + // no longer referenced by the plugin, but the FlutterViewController still maintains a transitive reference to it + // when the BinaryMessenger becomes invalid. + weak var uiView: UIView? - init(uiView: UIView) { - self.uiView = uiView - } + init(uiView: UIView) { + self.uiView = uiView + } - func view() -> UIView { + func view() -> UIView { + if let uiView = uiView { return uiView } + + NSLog( + "WebViewFlutterPluginError: UIView has been deallocated, but is still being requested as a PlatformView." + ) + return UIView() } - #endif + } +#endif + +/// Implementation of `FlutterPlatformViewFactory` that retrieves the view from the `WebKitLibraryPigeonInstanceManager`. +class FlutterViewFactory: NSObject, FlutterPlatformViewFactory { + unowned let instanceManager: WebKitLibraryPigeonInstanceManager init(instanceManager: WebKitLibraryPigeonInstanceManager) { self.instanceManager = instanceManager @@ -42,14 +55,9 @@ class FlutterViewFactory: NSObject, FlutterPlatformViewFactory { let identifier: Int64 = args is Int64 ? args as! Int64 : Int64(args as! Int32) let instance: AnyObject? = instanceManager.instance(forIdentifier: identifier) - if let instance = instance as? FlutterPlatformView { - instance.view().frame = frame - return instance - } else { - let view = instance as! UIView - view.frame = frame - return PlatformViewImpl(uiView: view) - } + let view = instance as! UIView + view.frame = frame + return PlatformViewImpl(uiView: view) } #elseif os(macOS) func create( diff --git a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml index 7217c1c55043..d61c43b4012a 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml @@ -2,7 +2,7 @@ name: webview_flutter_wkwebview description: A Flutter plugin that provides a WebView widget based on Apple's WKWebView control. repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter_wkwebview issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22 -version: 3.24.0 +version: 3.24.1 environment: sdk: ^3.9.0