当调用文件选择器时,WKWebview具有新的iOS13模式崩溃

Ant*_*tzi 9 uipopovercontroller ios wkwebview ios13

我在iOS13的模态视图控制器中有一个webview。当用户尝试将图像上传到Webview时,它崩溃。

这是我得到的例外:

2019-09-30 17:50:10.676940 + 0900 Engage [988:157733] *由于未捕获的异常'NSGenericException'而终止应用程序,原因:'您的应用程序已呈现UIDocumentMenuViewController()。在其当前特征环境中,具有此样式的UIDocumentMenuViewController的modalPresentationStyle为UIModalPresentationPopover。您必须通过视图控制器的popoverPresentationController提供此弹出窗口的位置信息。您必须提供sourceView和sourceRect或barButtonItem。如果在显示视图控制器时不知道此信息,则可以在UIPopoverPresentationControllerDelegate方法-prepareForPopoverPresentation中提供它。* 第一个抛出调用堆栈:(0x18926c98c 0x188f950a4 0x18cb898a8 0x18cb939b4 0x18cb914f8 0x18d283b98 0x18d2737c0 0x18d2a3594 0x1891e9c48 0x1891e4bc 0x1891e9d1 0x16e4d 0x18d2e4100 0x189dee4b 0160e1d4a3d00 0x189de2b3d00 0x189d1e4d3 0160e1d4a3 0160e1d4a3 0160e1d4a 0160e1d4a3d00 0x189de4b 0x189d1e6a3d00 0x189de2d6 1600x8001x6e 0x18d2e3d0 0x189de4d 1600x1x1e5d0 0x1891e4d3 0x1de1e6d00 0x189d1e6d3 1600x1x3d6 0x1e1d4a 0x1891e4d 0x1891e4d 0000

我不确定该在哪里设置这个代表...

我制作了一个示例项目:https : //github.com/ntnmrndn/WKUploadFormCrash 并向Apple提交了错误报告

2h4*_*h4u 6

正如@ jshapy8正确指出的那样,您需要重写present()方法并手动设置.sourceView/ .sourceFrame/ .barButtonItem。但是你要记住,万一UIViewController持有的WkWebView由提出UINavigationControllerUINavigationController是负责演示等UIViewController

除非您使用iPad。

因此,实际上您需要present()UINavigationController以及中UIViewController包含的方法中覆盖该方法WkWebView

在以下示例中,UIViewController包含的WkWebView称为WebVC

在你UINavigationController需要添加:

  override func present(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)? = nil) {
    if let webVC = viewControllers.filter({ $0 is WebVC }).first as? WebVC {
      webVC.setUIDocumentMenuViewControllerSoureViewsIfNeeded(viewControllerToPresent)
    }
    super.present(viewControllerToPresent, animated: flag, completion: completion)
  }
Run Code Online (Sandbox Code Playgroud)

并且WebVC您需要添加:

  override func present(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)? = nil) {
    setUIDocumentMenuViewControllerSoureViewsIfNeeded(viewControllerToPresent)
    super.present(viewControllerToPresent, animated: flag, completion: completion)
  }

  func setUIDocumentMenuViewControllerSoureViewsIfNeeded(_ viewControllerToPresent: UIViewController) {
    if #available(iOS 13, *), viewControllerToPresent is UIDocumentMenuViewController && UIDevice.current.userInterfaceIdiom == .phone {
      // Prevent the app from crashing if the WKWebView decides to present a UIDocumentMenuViewController while it self is presented modally.
      viewControllerToPresent.popoverPresentationController?.sourceView = webView
      viewControllerToPresent.popoverPresentationController?.sourceRect = CGRect(x: webView.center.x, y: webView.center.y, width: 1, height: 1)
    }
  }
Run Code Online (Sandbox Code Playgroud)

因此,您可以使用新的iOS 13模态演示样式并上传文件而不会崩溃

编辑:此崩溃的行为似乎是(另一个)iOS 13错误,因为这只是iPhone上的一个问题,而不是iPad上的(仅在使用iOS 12和13的iPad上进行了测试。这有点像苹果工程师忘记了,以防万一)将WKWebView呈现他们的新模式呈现的风格,UIDocumentMenuViewController呈现UIModalPresentationPopover的风格,甚至在手机上,这是直到iOS的13根本不是那么回事。

我更新了代码,现在它只为手机类型设置了.sourceView/ .sourceFrame/ .barButtonItem,因为平板电脑类型将由iOS自行正确处理。