WKWebView 不会打开社交媒体登录弹出窗口

Jus*_*ing 4 objective-c popup ios wkwebview

我的应用程序中有一个 WKWebView。除了我展示的网站有社交媒体登录按钮外,一切都运行顺利。问题是,它们会显示(或尝试显示)一个弹出窗口,您可以在其中允许它访问您的社交媒体帐户。我对此进行了研究并尝试了一些方法,但似乎都不适合。这是我尝试过的:

在 viewDidLoad 中,我尝试在 init 上启用 Javascript:

WKWebViewConfiguration *theConfiguration = [[WKWebViewConfiguration alloc] init];
WKPreferences *thePreferences = [[WKPreferences alloc] init];
thePreferences.javaScriptCanOpenWindowsAutomatically = YES;
thePreferences.javaScriptEnabled = YES;
theConfiguration.preferences = thePreferences;
self.wkWeb = [[WKWebView alloc] initWithFrame:screenRect configuration:theConfiguration];
Run Code Online (Sandbox Code Playgroud)

然而,这对我没有帮助。然后我试着和代表们一起玩,走那条路。我尝试使用 createWebViewWithConfiguration 方法,但这似乎有点矫枉过正,因为我必须过滤掉它们是否位于登录 URL 然后配置一个弹出窗口并显示它。然后这仍然不起作用。我也来这里查看如果不是主框架逻辑,取消请求并在主视图中重新加载它,这是一个简单的单行修复,因为它膨胀到 20 多行。

这似乎是一个常见问题,但我似乎无法在那里找到很多信息。有任何想法吗?

编辑 - 添加

在玩弄 Armands 的答案后,我走得更近了。这是我现在的 createWebViewWithConfig 方法,它只显示一个白屏覆盖。就像我需要一些东西来告诉新弹出窗口加载内容。另外 - 我假设我可以将这个模式窗口放在我当前的 .m 文件中并且它不需要一个全新的文件?

NSURL *url = navigationAction.request.URL;
if(!navigationAction.targetFrame.isMainFrame && [url.absoluteString rangeOfString:@"initiate_"].location != NSNotFound) {
    //open new modal webview
    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
    config.processPool = [appDelegate getSharedPool];

    self.popupLogin = [[WKWebView alloc] initWithFrame:self.wkWeb.bounds configuration:config];
    self.popupLogin.frame = CGRectMake(self.wkWeb.frame.origin.x,
                                       self.wkWeb.frame.origin.y,
                                       self.wkWeb.frame.size.width,
                                       self.wkWeb.frame.size.height);
    self.popupLogin.navigationDelegate = self;
    self.popupLogin.UIDelegate = self;
    [webView addSubview:self.popupLogin];
    [self.popupLogin loadRequest:navigationAction.request];
    return nil;
}
Run Code Online (Sandbox Code Playgroud)

Ras*_*tif 9

斯威夫特 4 和斯威夫特 5

创建WKWebView 的两个实例

var webView : WKWebView!
var newWebviewPopupWindow: WKWebView?
Run Code Online (Sandbox Code Playgroud)

现在实现方法

func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
        newWebviewPopupWindow = WKWebView(frame: view.bounds, configuration: configuration)
        newWebviewPopupWindow!.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        newWebviewPopupWindow!.navigationDelegate = self
        newWebviewPopupWindow!.uiDelegate = self
        view.addSubview(newWebviewPopupWindow!)
        return newWebviewPopupWindow!
    }

    func webViewDidClose(_ webView: WKWebView) {
        webView.removeFromSuperview()
        newWebviewPopupWindow = nil
    }
Run Code Online (Sandbox Code Playgroud)

如果您的代码仍然无法正常工作,还要确保Info.plist 中的此字符串。

 <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>
Run Code Online (Sandbox Code Playgroud)


Arm*_* L. 5

这些登录按钮尝试打开一个新选项卡,WKWebView 不支持该选项卡。据我所知,只有一种方法可以做到这一点。

首先添加WKUIDelegate方法:

-(WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
{
    NSURL *url = navigationAction.request.URL;
    if (navigationAction.targetFrame == nil && [url.absoluteString rangeOfString:@"facebook.com/dialog"].location != NSNotFound) {
        //Open new modal WKWebView
    }
    return nil;
}
Run Code Online (Sandbox Code Playgroud)

在模式 WKWebView 中添加:

-(void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
{
    NSURL *url = navigationResponse.response.URL;
    if ([url.absoluteString rangeOfString:@"close_popup.php"].location != NSNotFound) {
        //Close viewController
    }
    decisionHandler(WKNavigationResponsePolicyAllow);
}
Run Code Online (Sandbox Code Playgroud)

close_popup.php是给脸书的。如果您需要支持多个社交网络,请在其 URL 中找到一些独特的内容。

为了使其工作,您必须在 WKWebViews 之间共享 Cookie。为此,您必须使用 shared 初始化它们WKProcessPool。我更喜欢将它存储在 AppDelegate 中。

WKWebView 可以这样创建:

- (void)createWebView
{
    AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
    WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
    config.processPool = delegate.webViewProcessPool;

    self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config];
    self.webView.UIDelegate = self;
    self.webView.navigationDelegate = self;
    [self.view addSubview:self.webView];
}
Run Code Online (Sandbox Code Playgroud)

在 AppDelegate 中只是延迟加载它:

-(id)webViewProcessPool
{
    if (!_webViewProcessPool) {
        _webViewProcessPool = [[WKProcessPool alloc] init];
    }
    return _webViewProcessPool;
}
Run Code Online (Sandbox Code Playgroud)


Ale*_*exD 5

Armands 的回答是正确的,但可以显着改进。

  • 如果您希望 webview 能够相互协作(例如,通过 window.opener),返回新创建的 webview(而不是 nil)很重要
  • 如果您使用传递给 create 调用的配置,则会自动共享进程池
  • 您不需要在 createWebViewWith 调用中进行额外检查。(如果您想阻止任意弹出窗口或创建特定的 WebViewController 类型,您仍然应该将 URL 列入白名单。)

在您的主 WebViewController (其中webView.uiDelegate = self)中:

func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
    let webView = WKWebView.init(frame: .zero, configuration: configuration)

    //OPTIONAL: check navigationAction.request.url to see what site is being opened as a popup

    //TODO HERE: Launch new instance of your WebViewController (within a nav controller)
    //and pass it this newly created webView to be added as main subview

    return webView
}
Run Code Online (Sandbox Code Playgroud)

您仍然希望在弹出 WebViewController 的新实例中使用 close 侦听器(其中webView.navigationDelegate = self):

func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
    if let url = navigationResponse.response.url, url.absoluteString.hasPrefix("https://example.com/something-unique-to-this-popup-when-it-closes") {
        dismiss(animated: true, completion: nil)
    }
    decisionHandler(.allow)
}
Run Code Online (Sandbox Code Playgroud)