WKWebView操作表在被解雇后解除显示视图控制器

时间:2018-04-16 11:49:44

标签: ios swift wkwebview

我有一个嵌入在NavigationController中的视图控制器(WKWebViewController)。这个ViewController提供了一个WKWebView。导航到任何网页后;并且在长按任何检测到的内容(例如电话号码或链接)时,会显示一个操作表,其中包含复制,共享等选项。问题是当此操作表被取消时,WKWebViewController随之被解雇显示根ViewController!无论选择是什么,它都是复制,取消,甚至是在屏幕上的任何地方点击。

我已经尝试覆盖“ present(_ viewControllerToPresent:UIViewController,动画标志:Bool,完成:(() - > Void)?= nil)”和“解雇(动画标志:Bool,完成:(() - > Void)?)“试图理解发生了什么,但后来意识到行动表没有呈现,也没有被其父视图控制器解雇(WKWebViewController),事实上我在根视图控制器上做了同样的事情,发现它既没有出现在它上面。

我已经做了很多搜索,试图了解造成这种行为的原因,我甚至用一个简单的WKWebView构建了一个新项目,但总是遇到同样的问题。

以下是代码:

import UIKit; import WebKit
class WKWebViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {

var destinationUrlString: String?
var myWebView: WKWebView!

override func viewDidLoad() {
    super.viewDidLoad()

    let webConfiguration = WKWebViewConfiguration()
    webConfiguration.dataDetectorTypes = []
    let origin = CGPoint(x: 0, y: 0)
    let size  = CGSize(width: view.frame.size.width, height: view.frame.size.height)
    myWebView = WKWebView(frame: .init(origin: origin, size: size), configuration: webConfiguration)
    myWebView.uiDelegate = self
    myWebView.navigationDelegate = self
    myWebView.allowsLinkPreview = false
    view = myWebView

    destinationUrlString = "https://www.stackoverflow.com"
    guard let url = URL(string: destinationUrlString!) else {return}
    print(url)
    let request = URLRequest(url: url)
    myWebView.load(request)
}
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
    //show progress indicator
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    //dismiss progress indicator
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
    //show error
}
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
    //show error
}
}

我还附上了一个显示问题的GIF:

enter image description here

我正在使用Xcode 9.3(9E145)和Swift 4.1。

我错过了什么吗?怎么解决这个问题? 任何帮助都会非常感激。

3 个答案:

答案 0 :(得分:7)

我遇到了同样的问题。

要处理这种情况,在UIViewController层次结构的根视图控制器中(在您的情况下,这将是“根视图控制器” - 注意,在许多情况下它可能是{{1然后你必须继承)覆盖UINavgiationController以多次处理dismissViewControllerAnimated:completion:调用dismiss。

<强>目标C

WKWebView

<强>夫特

@property (weak) UIViewController *lastPresentedController;

- (void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion
{
    // WKWebView actions sheets workaround
    if (self.presentedViewController && self.lastPresentedController != self.presentedViewController ) {
        self.lastPresentedController = self.presentedViewController;
        [self.presentedViewController dismissViewControllerAnimated:YES completion:^{
            if( completion ) {
                completion();
            }
            self.lastPresentedController = nil;
        }];
    } else if( !self.lastPresentedController) {
        [super dismissViewControllerAnimated:flag completion:completion];
    }
}

答案 1 :(得分:1)

这必须是一个错误。如果在包含Web视图的viewController中覆盖 dismiss ,则当用户从操作表中选择任何操作时,将调用它。如果在dismiss重写中放置断点,则可以看到presentViewController的类型为WKActionSheet,它是一个内部类。他们可能会调用解雇来关闭操作表,然后逐渐剔除并解雇我们的视图控制器以容纳Web视图。您可以从该功能中返回以防止关闭,但之后他们选择的操作也不会发生。

如果您不想提交雷达,请告诉我,我会。

答案 2 :(得分:0)

- (void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion{
    if (@available(iOS 11, *)) {
        [super dismissViewControllerAnimated:flag completion:completion];
    }
    else{
        if ([self.topViewController isKindOfClass:[RTContainerController class]]){
            RTContainerController *topVC = (RTContainerController *)self.topViewController;
            if (![topVC.contentViewController isKindOfClass:NSClassFromString(@"MyWebViewController")]) {
                //让非 web 页面可以正常消失
                [self.topViewController dismissViewControllerAnimated:flag completion:completion];
            }else{
                //防止 web 页面消失
                if (self.presentedViewController) {
                    [self.presentedViewController dismissViewControllerAnimated:flag completion:completion];
                }
            }
        }else{
            if (self.presentedViewController) {
                [self.presentedViewController dismissViewControllerAnimated:flag completion:completion];
            }
        }
    }
}