8

I have a simple Swift project in which:

ViewController A (class ViewController: UIViewController) presents ViewController B -- (class WebViewController: UIViewController, WKNavigationDelegate, CLLocationManagerDelegate, WKScriptMessageHandler).

ViewController B is essentially just a WKWebView, here's its viewDidLoad():

let contentController = WKUserContentController();
contentController.addScriptMessageHandler(
    self,
    name: "eventHandler"
)

let config = WKWebViewConfiguration()
config.userContentController = contentController

webView = WKWebView(frame: CGRectZero, configuration: config)
webView.navigationDelegate = self
webView.allowsBackForwardNavigationGestures = false
view = webView

So, when ViewController B is presented, I basically just have a web browser on the entire screen.

The problem I'm running into is that, if the User (while on a webpage) clicks a "File Upload / File Picker", first I see this:

Passed in type public.item doesn't conform to either public.content or public.data. If you are exporting a new type, please ensure that it conforms to an appropriate parent type. the behavior of the UICollectionViewFlowLayout is not defined because the item width must be less than the width of the UICollectionView minus the section insets left and right values, minus the content insets left and right values.

The relevant UICollectionViewFlowLayout instance is <_UIAlertControllerCollectionViewFlowLayout: 0x12e30f270>, and it is attached to ; animations = { bounds.origin=; bounds.size=; position=; }; layer = ; contentOffset: {0, 0}; contentSize: {0, 0}> collection view layout: <_UIAlertControllerCollectionViewFlowLayout: 0x12e30f270>.

Then, if the User chooses "Take Photo or Video" or "Photo Library" from the iOS options list, I get this:

Warning: Attempt to present UIImagePickerController: 0x12d192200 on My.WebViewController: 0x12e2883e0 whose view is not in the window hierarchy!

The result is that:

  1. The photo library picker // camera app never appears.
  2. ViewController B undergoes an animated dismiss, for some reason.

Does anyone have any suggestions? I tried to provide the relevant code, but I can paste more if needed. Thank you.

-- UPDATE --------

Okay, so after more research, there are actually two separate things going on:

  1. The first error is a function of how the "file picker" is handled by a mobile browser. See here ... grand scheme of things, not a big deal.

  2. The second error Attempt to present UIImagePickerController... -- the more debilitating of the two -- is uglier.

If a ViewController with a WKWebView is presented from another ViewController then, upon the User trying to "pick" an image (from library or camera), iOS will attempt to present the UIImagePicker from your WKWebView ViewController, which is what you want.

Unfortunately, for a reason I don't yet know, the act of the User trying to "pick" an image also causes iOS to dismiss the presented view controller ... which, in this case, is your WKWebView controller :( As such, the WKWebView ViewController dismisses, so it then isn't in the window hierarchy when it attempts to present the UIImagePicker -- hence, the error.

My solution (which is pretty hacky, but works for my particular use case), is as follows; I hope this helps someone:

  1. Instantiate the WKWebView ViewController (ViewController B)
  2. Set VC B as the app's root view controller
  3. Present VC B from ViewController A
  4. Dismiss VC A

This essentially makes it so the WKWebView cannot be dismissed, sidestepping the problem.

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("Browser") as! WebViewController
UIApplication.sharedApplication().keyWindow?.rootViewController = vc

self.presentViewController(vc, animated: false, completion: { () -> Void in
    self.dismissViewControllerAnimated(false, completion: nil)
})
Dan
  • 4,197
  • 6
  • 34
  • 52
  • I have the same situation right now. As for first issue: it only appears on simulator, but not on actual device. The second issue is resolved by answer from https://stackoverflow.com/questions/37380333 – Jurasic May 30 '17 at 09:18

1 Answers1

1

If you are doing int in viewDidLoad(){} function currently then try to move code into override viewDidAppear(animated: Bool) {} I had the same problem today and it fixed it.

Tarvo Mäesepp
  • 4,477
  • 3
  • 44
  • 92