Flutter Webview setcookie 在 iOS-Wkwebview 首次进程不生效的解决方法
2024-01-27 01:30:14
解决 Flutter Webview setCookie 在 iOS-Wkwebview 首次进程不生效的 Bug
在 Flutter Webview 中使用 setCookie 方法在 iOS-Wkwebview 上设置 Cookie 时,可能会遇到首次进程不生效的 Bug。这是由于 iOS 中 WKwebview 采用的沙箱机制造成的。本文将深入探讨这个问题的根源并提供一种有效的解决方法。
问题根源
iOS 上的 WKwebview 采用了沙箱机制,将 Web 内容与 App 隔离。这意味着当首次设置 Cookie 时,Cookie 会被添加到 WKwebview 的沙箱中。但是,由于沙箱机制,这些 Cookie 无法被 App 进程直接读取。只有在终止进程并重新打开后,App 进程才能获取到 Cookie。
解决方法
要解决此 Bug,需要修改 iOS 端的代码。具体步骤如下:
1. 修改 iOS 端代码
- 在 iOS 端的 AppDelegate.m 中,找到 WKUserContentController 对象。
- 添加以下代码:
- (void)userContentController:(nonnull WKUserContentController *)userContentController didReceiveScriptMessage:(nonnull WKScriptMessage *)message {
if ([message.name isEqualToString:@"setCookie"]) {
NSDictionary *cookieDict = message.body;
NSHTTPCookie *cookie = [[NSHTTPCookie alloc]initWithProperties:cookieDict];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie domain:nil path:@"/" secure:NO excludesSubdomains:NO];
}
}
2. 重新编译 App
- 修改代码后,重新编译 App。
3. 重新打开 App
- 重新打开 App,此时第一次设置的 Cookie 就会生效。
代码示例
以下是一个代码示例,展示了解决方法的实际实现:
// Flutter Webview 代码
import 'package:flutter/services.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
class WebViewExample extends StatefulWidget {
@override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<WebviewExample> {
@override
void initState() {
super.initState();
// 监听 WebView 的消息
FlutterWebviewPlugin().onUrlChanged.listen((String url) {});
FlutterWebviewPlugin().onWebviewMessage.listen((WebviewMessage message) {
if (message.data == "setCookie") {
// 在 iOS WKwebview 中设置 Cookie
FlutterWebviewPlugin().evalJavascript("document.cookie = 'name=value'");
}
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: WebviewScaffold(
url: "https://example.com", // 替换为你的网站 URL
javascriptMode: JavascriptMode.unrestricted,
mediaPlaybackPolicy: MediaPlaybackPolicy.requireUserActionForMediaPlayback,
withZoom: false,
withLocalStorage: true,
withJavascript: true,
),
);
}
}
// iOS 端代码
- (void)userContentController:(nonnull WKUserContentController *)userContentController didReceiveScriptMessage:(nonnull WKScriptMessage *)message {
if ([message.name isEqualToString:@"setCookie"]) {
NSDictionary *cookieDict = message.body;
NSHTTPCookie *cookie = [[NSHTTPCookie alloc]initWithProperties:cookieDict];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie domain:nil path:@"/" secure:NO excludesSubdomains:NO];
}
}
注意事项
- 该方法仅适用于 iOS 上的 WKwebview。
- 如果在 iOS 上使用的是 UIwebview,则不需要使用该方法。
- 该方法需要修改 iOS 端的代码,可能需要重新编译 App。
总结
在 Flutter 中,使用 Webview 设置 Cookie 在 iOS-Wkwebview 首次进程不生效的 Bug 源于 WKwebview 的沙箱机制。通过修改 iOS 端代码并重新编译 App,可以有效解决此 Bug。遵循本文提供的步骤,即可轻松实现这一操作,从而确保在 iOS-Wkwebview 上设置 Cookie 时达到预期效果。
常见问题解答
-
此方法是否适用于所有版本的 iOS 和 Flutter?
该方法适用于 iOS 13 及更高版本和 Flutter 3 及更高版本。 -
为什么需要修改 iOS 端的代码?
因为 WKwebview 的沙箱机制,App 进程无法直接访问首次设置的 Cookie。修改 iOS 代码可以绕过此限制。 -
我需要重新编译整个 App 吗?
是的,需要重新编译整个 App,以便修改后的 iOS 代码生效。 -
除了本文提供的解决方案外,还有其他方法可以解决此 Bug 吗?
目前,修改 iOS 代码是唯一已知有效的解决方案。 -
此方法是否适用于所有 Webview 库?
此方法仅适用于 Flutter 中使用的 Flutter Webview Plugin 库。