Managed iOS native detachFromEngine flutter plugin event and updated dispose methods, Updated Android native HeadlessInAppWebViewManager.dispose and HeadlessInAppWebView.dispose methods

This commit is contained in:
Lorenzo Pichilli 2022-04-23 04:02:37 +02:00
parent d1e4dc55d0
commit 2d31a2f58b
25 changed files with 245 additions and 58 deletions

View File

@ -1,3 +1,8 @@
## 5.4.1
- Managed iOS native `detachFromEngine` flutter plugin event and updated `dispose` methods
- Updated Android native `HeadlessInAppWebViewManager.dispose` and `HeadlessInAppWebView.dispose` methods
## 5.4.0+3
- Fixed Android error in some cases when calling `setServiceWorkerClient` java method on `ServiceWorkerManager` initialization

View File

@ -110,12 +110,16 @@ public class HeadlessInAppWebView implements MethodChannel.MethodCallHandler {
public void dispose() {
channel.setMethodCallHandler(null);
HeadlessInAppWebViewManager.webViews.remove(id);
ViewGroup contentView = (ViewGroup) plugin.activity.findViewById(android.R.id.content);
ViewGroup mainView = (ViewGroup) (contentView).getChildAt(0);
if (mainView != null) {
mainView.removeView(flutterWebView.getView());
if (plugin != null) {
ViewGroup contentView = (ViewGroup) plugin.activity.findViewById(android.R.id.content);
ViewGroup mainView = (ViewGroup) (contentView).getChildAt(0);
if (mainView != null && flutterWebView != null) {
mainView.removeView(flutterWebView.getView());
}
}
if (flutterWebView != null) {
flutterWebView.dispose();
}
flutterWebView.dispose();
flutterWebView = null;
plugin = null;
}

View File

@ -26,7 +26,9 @@ import androidx.annotation.Nullable;
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
import com.pichillilorenzo.flutter_inappwebview.in_app_webview.FlutterWebView;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import io.flutter.plugin.common.MethodCall;
@ -77,6 +79,10 @@ public class HeadlessInAppWebViewManager implements MethodChannel.MethodCallHand
public void dispose() {
channel.setMethodCallHandler(null);
Collection<HeadlessInAppWebView> headlessInAppWebViews = webViews.values();
for (HeadlessInAppWebView headlessInAppWebView : headlessInAppWebViews) {
headlessInAppWebView.dispose();
}
webViews.clear();
}
}

View File

@ -31,7 +31,11 @@ class CredentialDatabase: NSObject, FlutterPlugin {
switch call.method {
case "getAllAuthCredentials":
var allCredentials: [[String: Any?]] = []
for (protectionSpace, credentials) in CredentialDatabase.credentialStore!.allCredentials {
guard let credentialStore = CredentialDatabase.credentialStore else {
result(allCredentials)
return
}
for (protectionSpace, credentials) in credentialStore.allCredentials {
var crendentials: [[String: Any?]] = []
for c in credentials {
let credential: [String: Any?] = c.value.toMap()
@ -43,10 +47,17 @@ class CredentialDatabase: NSObject, FlutterPlugin {
"credentials": crendentials
]
allCredentials.append(dict)
} }
}
}
result(allCredentials)
break
case "getHttpAuthCredentials":
var crendentials: [[String: Any?]] = []
guard let credentialStore = CredentialDatabase.credentialStore else {
result(crendentials)
return
}
let host = arguments!["host"] as! String
let urlProtocol = arguments!["protocol"] as? String
let urlPort = arguments!["port"] as? Int ?? 0
@ -54,9 +65,8 @@ class CredentialDatabase: NSObject, FlutterPlugin {
if let r = realm, r.isEmpty {
realm = nil
}
var crendentials: [[String: Any?]] = []
for (protectionSpace, credentials) in CredentialDatabase.credentialStore!.allCredentials {
for (protectionSpace, credentials) in credentialStore.allCredentials {
if protectionSpace.host == host && protectionSpace.realm == realm &&
protectionSpace.protocol == urlProtocol && protectionSpace.port == urlPort {
for c in credentials {
@ -68,6 +78,11 @@ class CredentialDatabase: NSObject, FlutterPlugin {
result(crendentials)
break
case "setHttpAuthCredential":
guard let credentialStore = CredentialDatabase.credentialStore else {
result(false)
return
}
let host = arguments!["host"] as! String
let urlProtocol = arguments!["protocol"] as? String
let urlPort = arguments!["port"] as? Int ?? 0
@ -78,11 +93,17 @@ class CredentialDatabase: NSObject, FlutterPlugin {
let username = arguments!["username"] as! String
let password = arguments!["password"] as! String
let credential = URLCredential(user: username, password: password, persistence: .permanent)
CredentialDatabase.credentialStore!.set(credential,
for: URLProtectionSpace(host: host, port: urlPort, protocol: urlProtocol, realm: realm, authenticationMethod: NSURLAuthenticationMethodHTTPBasic))
credentialStore.set(credential,
for: URLProtectionSpace(host: host, port: urlPort, protocol: urlProtocol,
realm: realm, authenticationMethod: NSURLAuthenticationMethodHTTPBasic))
result(true)
break
case "removeHttpAuthCredential":
guard let credentialStore = CredentialDatabase.credentialStore else {
result(false)
return
}
let host = arguments!["host"] as! String
let urlProtocol = arguments!["protocol"] as? String
let urlPort = arguments!["port"] as? Int ?? 0
@ -96,7 +117,7 @@ class CredentialDatabase: NSObject, FlutterPlugin {
var credential: URLCredential? = nil;
var protectionSpaceCredential: URLProtectionSpace? = nil
for (protectionSpace, credentials) in CredentialDatabase.credentialStore!.allCredentials {
for (protectionSpace, credentials) in credentialStore.allCredentials {
if protectionSpace.host == host && protectionSpace.realm == realm &&
protectionSpace.protocol == urlProtocol && protectionSpace.port == urlPort {
for c in credentials {
@ -113,12 +134,17 @@ class CredentialDatabase: NSObject, FlutterPlugin {
}
if let c = credential, let protectionSpace = protectionSpaceCredential {
CredentialDatabase.credentialStore!.remove(c, for: protectionSpace)
credentialStore.remove(c, for: protectionSpace)
}
result(true)
break
case "removeHttpAuthCredentials":
guard let credentialStore = CredentialDatabase.credentialStore else {
result(false)
return
}
let host = arguments!["host"] as! String
let urlProtocol = arguments!["protocol"] as? String
let urlPort = arguments!["port"] as? Int ?? 0
@ -130,7 +156,7 @@ class CredentialDatabase: NSObject, FlutterPlugin {
var credentialsToRemove: [URLCredential] = [];
var protectionSpaceCredential: URLProtectionSpace? = nil
for (protectionSpace, credentials) in CredentialDatabase.credentialStore!.allCredentials {
for (protectionSpace, credentials) in credentialStore.allCredentials {
if protectionSpace.host == host && protectionSpace.realm == realm &&
protectionSpace.protocol == urlProtocol && protectionSpace.port == urlPort {
protectionSpaceCredential = protectionSpace
@ -145,16 +171,21 @@ class CredentialDatabase: NSObject, FlutterPlugin {
if let protectionSpace = protectionSpaceCredential {
for credential in credentialsToRemove {
CredentialDatabase.credentialStore!.remove(credential, for: protectionSpace)
credentialStore.remove(credential, for: protectionSpace)
}
}
result(true)
break
case "clearAllAuthCredentials":
for (protectionSpace, credentials) in CredentialDatabase.credentialStore!.allCredentials {
guard let credentialStore = CredentialDatabase.credentialStore else {
result(false)
return
}
for (protectionSpace, credentials) in credentialStore.allCredentials {
for credential in credentials {
CredentialDatabase.credentialStore!.remove(credential.value, for: protectionSpace)
credentialStore.remove(credential.value, for: protectionSpace)
}
}
result(true)
@ -164,4 +195,11 @@ class CredentialDatabase: NSObject, FlutterPlugin {
break
}
}
public func dispose() {
CredentialDatabase.channel?.setMethodCallHandler(nil)
CredentialDatabase.channel = nil
CredentialDatabase.registrar = nil
CredentialDatabase.credentialStore = nil
}
}

View File

@ -57,4 +57,15 @@ public class HeadlessInAppWebViewManager: NSObject, FlutterPlugin {
headlessInAppWebView.onWebViewCreated()
flutterWebView.makeInitialLoad(params: params as NSDictionary)
}
public func dispose() {
HeadlessInAppWebViewManager.channel?.setMethodCallHandler(nil)
HeadlessInAppWebViewManager.channel = nil
HeadlessInAppWebViewManager.registrar = nil
let headlessWebViews = HeadlessInAppWebViewManager.webViews.values
headlessWebViews.forEach { (headlessWebView: HeadlessInAppWebView) in
headlessWebView.dispose()
}
HeadlessInAppWebViewManager.webViews.removeAll()
}
}

View File

@ -140,4 +140,10 @@ public class InAppBrowserManager: NSObject, FlutterPlugin {
}
result(true)
}
public func dispose() {
InAppBrowserManager.channel?.setMethodCallHandler(nil)
InAppBrowserManager.channel = nil
InAppBrowserManager.registrar = nil
}
}

View File

@ -182,6 +182,7 @@ public class InAppBrowserWebViewController: UIViewController, InAppBrowserDelega
deinit {
print("InAppBrowserWebViewController - dealloc")
dispose()
}
public override func viewDidDisappear(_ animated: Bool) {
@ -550,7 +551,10 @@ public class InAppBrowserWebViewController: UIViewController, InAppBrowserDelega
}
public func dispose() {
webView.dispose()
onExit()
channel?.setMethodCallHandler(nil)
channel = nil
webView?.dispose()
webView = nil
view = nil
if previousStatusBarStyle != -1 {
@ -563,18 +567,15 @@ public class InAppBrowserWebViewController: UIViewController, InAppBrowserDelega
backButton.target = nil
reloadButton.target = nil
shareButton.target = nil
onExit()
channel?.setMethodCallHandler(nil)
channel = nil
methodCallDelegate?.webView = nil
methodCallDelegate = nil
}
public func onBrowserCreated() {
channel!.invokeMethod("onBrowserCreated", arguments: [])
channel?.invokeMethod("onBrowserCreated", arguments: [])
}
public func onExit() {
channel!.invokeMethod("onExit", arguments: [])
channel?.invokeMethod("onExit", arguments: [])
}
}

View File

@ -164,7 +164,8 @@ public class FlutterWebViewController: NSObject, FlutterPlatformView {
func dispose() {
channel?.setMethodCallHandler(nil)
methodCallDelegate?.webView = nil
channel = nil
methodCallDelegate?.dispose()
methodCallDelegate = nil
webView?.dispose()
webView = nil

View File

@ -1673,8 +1673,8 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
completionHandler(.useCredential, credential)
break
case 2:
if InAppWebView.credentialsProposed.count == 0 {
for (protectionSpace, credentials) in CredentialDatabase.credentialStore!.allCredentials {
if InAppWebView.credentialsProposed.count == 0, let credentialStore = CredentialDatabase.credentialStore {
for (protectionSpace, credentials) in credentialStore.allCredentials {
if protectionSpace.host == host && protectionSpace.realm == realm &&
protectionSpace.protocol == prot && protectionSpace.port == port {
for credential in credentials {
@ -2900,6 +2900,12 @@ if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) {
}
public func dispose() {
channel = nil
removeObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress))
removeObserver(self, forKeyPath: #keyPath(WKWebView.url))
removeObserver(self, forKeyPath: #keyPath(WKWebView.title))
scrollView.removeObserver(self, forKeyPath: #keyPath(UIScrollView.contentOffset))
scrollView.removeObserver(self, forKeyPath: #keyPath(UIScrollView.zoomScale))
resumeTimers()
stopLoading()
disposeWebMessageChannels()
@ -2920,15 +2926,10 @@ if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) {
InAppWebView.windowWebViews.removeValue(forKey: wId)
}
configuration.userContentController.dispose(windowId: windowId)
removeObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress))
removeObserver(self, forKeyPath: #keyPath(WKWebView.url))
removeObserver(self, forKeyPath: #keyPath(WKWebView.title))
NotificationCenter.default.removeObserver(self)
for imp in customIMPs {
imp_removeBlock(imp)
}
scrollView.removeObserver(self, forKeyPath: #keyPath(UIScrollView.contentOffset))
scrollView.removeObserver(self, forKeyPath: #keyPath(UIScrollView.zoomScale))
longPressRecognizer.removeTarget(self, action: #selector(longPressGestureDetected))
longPressRecognizer.delegate = nil
scrollView.removeGestureRecognizer(longPressRecognizer)
@ -2945,7 +2946,6 @@ if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) {
navigationDelegate = nil
scrollView.delegate = nil
isPausedTimersCompletionHandler = nil
channel = nil
SharedLastTouchPointTimestamp.removeValue(forKey: self)
callAsyncJavaScriptBelowIOS14Results.removeAll()
super.removeFromSuperview()

View File

@ -553,8 +553,12 @@ public class InAppWebViewMethodHandler: FlutterMethodCallDelegate {
}
}
deinit {
print("InAppWebViewMethodHandler - dealloc")
public func dispose() {
webView = nil
}
deinit {
print("InAppWebViewMethodHandler - dealloc")
dispose()
}
}

View File

@ -72,4 +72,12 @@ class InAppWebViewStatic: NSObject, FlutterPlugin {
completionHandler(defaultUserAgent)
}
}
public func dispose() {
InAppWebViewStatic.channel?.setMethodCallHandler(nil)
InAppWebViewStatic.channel = nil
InAppWebViewStatic.registrar = nil
InAppWebViewStatic.webViewForUserAgent = nil
InAppWebViewStatic.defaultUserAgent = nil
}
}

View File

@ -100,6 +100,11 @@ class MyCookieManager: NSObject, FlutterPlugin {
isHttpOnly: Bool?,
sameSite: String?,
result: @escaping FlutterResult) {
guard let httpCookieStore = MyCookieManager.httpCookieStore else {
result(false)
return
}
var properties: [HTTPCookiePropertyKey: Any] = [:]
properties[.originURL] = url
properties[.name] = name
@ -138,7 +143,7 @@ class MyCookieManager: NSObject, FlutterPlugin {
let cookie = HTTPCookie(properties: properties)!
MyCookieManager.httpCookieStore!.setCookie(cookie, completionHandler: {() in
httpCookieStore.setCookie(cookie, completionHandler: {() in
result(true)
})
}
@ -146,8 +151,13 @@ class MyCookieManager: NSObject, FlutterPlugin {
public static func getCookies(url: String, result: @escaping FlutterResult) {
var cookieList: [[String: Any?]] = []
guard let httpCookieStore = MyCookieManager.httpCookieStore else {
result(cookieList)
return
}
if let urlHost = URL(string: url)?.host {
MyCookieManager.httpCookieStore!.getAllCookies { (cookies) in
httpCookieStore.getAllCookies { (cookies) in
for cookie in cookies {
if urlHost.hasSuffix(cookie.domain) || ".\(urlHost)".hasSuffix(cookie.domain) {
var sameSite: String? = nil
@ -189,7 +199,12 @@ class MyCookieManager: NSObject, FlutterPlugin {
public static func getAllCookies(result: @escaping FlutterResult) {
var cookieList: [[String: Any?]] = []
MyCookieManager.httpCookieStore!.getAllCookies { (cookies) in
guard let httpCookieStore = MyCookieManager.httpCookieStore else {
result(cookieList)
return
}
httpCookieStore.getAllCookies { (cookies) in
for cookie in cookies {
var sameSite: String? = nil
if #available(iOS 13.0, *) {
@ -221,7 +236,12 @@ class MyCookieManager: NSObject, FlutterPlugin {
}
public static func deleteCookie(url: String, name: String, domain: String, path: String, result: @escaping FlutterResult) {
MyCookieManager.httpCookieStore!.getAllCookies { (cookies) in
guard let httpCookieStore = MyCookieManager.httpCookieStore else {
result(false)
return
}
httpCookieStore.getAllCookies { (cookies) in
for cookie in cookies {
var originURL = ""
if cookie.properties![.originURL] is String {
@ -234,7 +254,7 @@ class MyCookieManager: NSObject, FlutterPlugin {
continue
}
if (cookie.domain == domain || cookie.domain == ".\(domain)" || ".\(cookie.domain)" == domain) && cookie.name == name && cookie.path == path {
MyCookieManager.httpCookieStore!.delete(cookie, completionHandler: {
httpCookieStore.delete(cookie, completionHandler: {
result(true)
})
return
@ -245,7 +265,12 @@ class MyCookieManager: NSObject, FlutterPlugin {
}
public static func deleteCookies(url: String, domain: String, path: String, result: @escaping FlutterResult) {
MyCookieManager.httpCookieStore!.getAllCookies { (cookies) in
guard let httpCookieStore = MyCookieManager.httpCookieStore else {
result(false)
return
}
httpCookieStore.getAllCookies { (cookies) in
for cookie in cookies {
var originURL = ""
if cookie.properties![.originURL] is String {
@ -258,7 +283,7 @@ class MyCookieManager: NSObject, FlutterPlugin {
continue
}
if (cookie.domain == domain || cookie.domain == ".\(domain)" || ".\(cookie.domain)" == domain) && cookie.path == path {
MyCookieManager.httpCookieStore!.delete(cookie, completionHandler: nil)
httpCookieStore.delete(cookie, completionHandler: nil)
}
}
result(true)
@ -272,4 +297,11 @@ class MyCookieManager: NSObject, FlutterPlugin {
result(true)
})
}
public func dispose() {
MyCookieManager.channel?.setMethodCallHandler(nil)
MyCookieManager.channel = nil
MyCookieManager.registrar = nil
MyCookieManager.httpCookieStore = nil
}
}

View File

@ -53,7 +53,13 @@ class MyWebStorageManager: NSObject, FlutterPlugin {
public static func fetchDataRecords(dataTypes: Set<String>, result: @escaping FlutterResult) {
var recordList: [[String: Any?]] = []
MyWebStorageManager.websiteDataStore!.fetchDataRecords(ofTypes: dataTypes) { (data) in
guard let websiteDataStore = MyWebStorageManager.websiteDataStore else {
result(recordList)
return
}
websiteDataStore.fetchDataRecords(ofTypes: dataTypes) { (data) in
for record in data {
recordList.append([
"displayName": record.displayName,
@ -68,7 +74,13 @@ class MyWebStorageManager: NSObject, FlutterPlugin {
public static func removeDataFor(dataTypes: Set<String>, recordList: [[String: Any?]], result: @escaping FlutterResult) {
var records: [WKWebsiteDataRecord] = []
MyWebStorageManager.websiteDataStore!.fetchDataRecords(ofTypes: dataTypes) { (data) in
guard let websiteDataStore = MyWebStorageManager.websiteDataStore else {
result(false)
return
}
websiteDataStore.fetchDataRecords(ofTypes: dataTypes) { (data) in
for record in data {
for r in recordList {
let displayName = r["displayName"] as! String
@ -78,16 +90,28 @@ class MyWebStorageManager: NSObject, FlutterPlugin {
}
}
}
MyWebStorageManager.websiteDataStore!.removeData(ofTypes: dataTypes, for: records) {
websiteDataStore.removeData(ofTypes: dataTypes, for: records) {
result(true)
}
}
}
public static func removeDataModifiedSince(dataTypes: Set<String>, timestamp: Int64, result: @escaping FlutterResult) {
guard let websiteDataStore = MyWebStorageManager.websiteDataStore else {
result(false)
return
}
let date = NSDate(timeIntervalSince1970: TimeInterval(timestamp))
MyWebStorageManager.websiteDataStore!.removeData(ofTypes: dataTypes, modifiedSince: date as Date) {
websiteDataStore.removeData(ofTypes: dataTypes, modifiedSince: date as Date) {
result(true)
}
}
public func dispose() {
MyWebStorageManager.channel?.setMethodCallHandler(nil)
MyWebStorageManager.channel = nil
MyWebStorageManager.registrar = nil
MyWebStorageManager.websiteDataStore = nil
}
}

View File

@ -60,4 +60,10 @@ class PlatformUtil: NSObject, FlutterPlugin {
formatter.timeZone = timezone
return formatter.string(from: PlatformUtil.getDateFromMilliseconds(date: date))
}
public func dispose() {
PlatformUtil.channel?.setMethodCallHandler(nil)
PlatformUtil.channel = nil
PlatformUtil.registrar = nil
}
}

View File

@ -109,5 +109,6 @@ public class PullToRefreshControl : UIRefreshControl, FlutterPlugin {
deinit {
print("PullToRefreshControl - dealloc")
dispose()
}
}

View File

@ -91,4 +91,10 @@ public class ChromeSafariBrowserManager: NSObject, FlutterPlugin {
result(FlutterError.init(code: "ChromeSafariBrowserManager", message: "SafariViewController is not available!", details: nil))
}
public func dispose() {
ChromeSafariBrowserManager.channel?.setMethodCallHandler(nil)
ChromeSafariBrowserManager.channel = nil
ChromeSafariBrowserManager.registrar = nil
}
}

View File

@ -22,6 +22,7 @@ public class SafariViewController: SFSafariViewController, FlutterPlugin, SFSafa
deinit {
print("SafariViewController - dealloc")
dispose()
}
public func prepareMethodChannel() {
@ -123,20 +124,21 @@ public class SafariViewController: SFSafariViewController, FlutterPlugin, SFSafa
// }
public func onChromeSafariBrowserOpened() {
channel!.invokeMethod("onChromeSafariBrowserOpened", arguments: [])
channel?.invokeMethod("onChromeSafariBrowserOpened", arguments: [])
}
public func onChromeSafariBrowserCompletedInitialLoad() {
channel!.invokeMethod("onChromeSafariBrowserCompletedInitialLoad", arguments: [])
channel?.invokeMethod("onChromeSafariBrowserCompletedInitialLoad", arguments: [])
}
public func onChromeSafariBrowserClosed() {
channel!.invokeMethod("onChromeSafariBrowserClosed", arguments: [])
channel?.invokeMethod("onChromeSafariBrowserClosed", arguments: [])
}
public func dispose() {
channel?.setMethodCallHandler(nil)
channel = nil
delegate = nil
channel!.setMethodCallHandler(nil)
}
}
@ -180,7 +182,12 @@ class CustomUIActivity : UIActivity {
}
override func perform() {
let channel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_chromesafaribrowser_" + viewId, binaryMessenger: SwiftFlutterPlugin.instance!.registrar!.messenger())
guard let registrar = SwiftFlutterPlugin.instance?.registrar else {
return
}
let channel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_chromesafaribrowser_" + viewId,
binaryMessenger: registrar.messenger())
let arguments: [String: Any?] = [
"url": url.absoluteString,

View File

@ -49,16 +49,39 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
headlessInAppWebViewManager = HeadlessInAppWebViewManager(registrar: registrar)
chromeSafariBrowserManager = ChromeSafariBrowserManager(registrar: registrar)
inAppWebViewStatic = InAppWebViewStatic(registrar: registrar)
credentialDatabase = CredentialDatabase(registrar: registrar)
if #available(iOS 11.0, *) {
myCookieManager = MyCookieManager(registrar: registrar)
}
if #available(iOS 9.0, *) {
myWebStorageManager = MyWebStorageManager(registrar: registrar)
}
credentialDatabase = CredentialDatabase(registrar: registrar)
}
public static func register(with registrar: FlutterPluginRegistrar) {
SwiftFlutterPlugin.instance = SwiftFlutterPlugin(with: registrar)
}
public func detachFromEngine(for registrar: FlutterPluginRegistrar) {
platformUtil?.dispose()
platformUtil = nil
inAppBrowserManager?.dispose()
inAppBrowserManager = nil
headlessInAppWebViewManager?.dispose()
headlessInAppWebViewManager = nil
chromeSafariBrowserManager?.dispose()
chromeSafariBrowserManager = nil
inAppWebViewStatic?.dispose()
inAppWebViewStatic = nil
credentialDatabase?.dispose()
credentialDatabase = nil
if #available(iOS 11.0, *) {
(myCookieManager as! MyCookieManager?)?.dispose()
myCookieManager = nil
}
if #available(iOS 9.0, *) {
(myWebStorageManager as! MyWebStorageManager?)?.dispose()
myWebStorageManager = nil
}
}
}

View File

@ -21,7 +21,7 @@ extension WKUserContentController {
var contentWorlds: Set<WKContentWorld> {
get {
let tmpAddress = String(format: "%p", unsafeBitCast(self, to: Int.self))
return WKUserContentController._contentWorlds[tmpAddress]!
return WKUserContentController._contentWorlds[tmpAddress] ?? []
}
set(newValue) {
let tmpAddress = String(format: "%p", unsafeBitCast(self, to: Int.self))
@ -33,7 +33,7 @@ extension WKUserContentController {
var userOnlyScripts: [WKUserScriptInjectionTime:OrderedSet<UserScript>] {
get {
let tmpAddress = String(format: "%p", unsafeBitCast(self, to: Int.self))
return WKUserContentController._userOnlyScripts[tmpAddress]!
return WKUserContentController._userOnlyScripts[tmpAddress] ?? [:]
}
set(newValue) {
let tmpAddress = String(format: "%p", unsafeBitCast(self, to: Int.self))
@ -45,7 +45,7 @@ extension WKUserContentController {
var pluginScripts: [WKUserScriptInjectionTime:OrderedSet<PluginScript>] {
get {
let tmpAddress = String(format: "%p", unsafeBitCast(self, to: Int.self))
return WKUserContentController._pluginScripts[tmpAddress]!
return WKUserContentController._pluginScripts[tmpAddress] ?? [:]
}
set(newValue) {
let tmpAddress = String(format: "%p", unsafeBitCast(self, to: Int.self))

View File

@ -23,5 +23,6 @@ public class WebMessage : NSObject {
deinit {
print("WebMessage - dealloc")
dispose()
}
}

View File

@ -126,6 +126,7 @@ public class WebMessageChannel : FlutterMethodCallDelegate {
public func dispose() {
channel?.setMethodCallHandler(nil)
channel = nil
for port in ports {
port.dispose()
}
@ -140,11 +141,11 @@ public class WebMessageChannel : FlutterMethodCallDelegate {
}
})();
""")
channel = nil
webView = nil
}
deinit {
print("WebMessageChannel - dealloc")
dispose()
}
}

View File

@ -222,5 +222,6 @@ public class WebMessageListener : FlutterMethodCallDelegate {
deinit {
print("WebMessageListener - dealloc")
dispose()
}
}

View File

@ -118,5 +118,6 @@ public class WebMessagePort : NSObject {
deinit {
print("WebMessagePort - dealloc")
dispose()
}
}

View File

@ -12,7 +12,7 @@ var SharedLastTouchPointTimestamp: [InAppWebView: Int64] = [:]
public class Util {
public static func getUrlAsset(assetFilePath: String) throws -> URL {
let key = SwiftFlutterPlugin.instance!.registrar!.lookupKey(forAsset: assetFilePath)
let key = SwiftFlutterPlugin.instance?.registrar?.lookupKey(forAsset: assetFilePath)
guard let assetURL = Bundle.main.url(forResource: key, withExtension: nil) else {
throw NSError(domain: assetFilePath + " asset file cannot be found!", code: 0)
}
@ -20,7 +20,7 @@ public class Util {
}
public static func getAbsPathAsset(assetFilePath: String) throws -> String {
let key = SwiftFlutterPlugin.instance!.registrar!.lookupKey(forAsset: assetFilePath)
let key = SwiftFlutterPlugin.instance?.registrar?.lookupKey(forAsset: assetFilePath)
guard let assetAbsPath = Bundle.main.path(forResource: key, ofType: nil) else {
throw NSError(domain: assetFilePath + " asset file cannot be found!", code: 0)
}

View File

@ -1,6 +1,6 @@
name: flutter_inappwebview
description: A Flutter plugin that allows you to add an inline webview, to use an headless webview, and to open an in-app browser window.
version: 5.4.0+3
version: 5.4.1
homepage: https://github.com/pichillilorenzo/flutter_inappwebview
environment: