locked
(iOS8) UIWebView and Input Tag, Type=File Crashes Application RRS feed

  • Question

  • User64419 posted

    I have a simple UIWebView project as a test bed to see how I can utilize the file type input tag for uploading a local file from an iOS device to a server. I have seen a functioning demo here (https://longhandpixels.net/demos/mobilesafari-ios6/), if I navigate to this site on an iPad, I am able to select an image or video (as well as launch the camera app). However, when I apply the same basic HTML into a test file and add it into my application, it crashes the app when I select the "Choose file" button. What would be the difference between Safari and UIWebView in this case that would cause it to crash? I though that the UIWebView was a containerized version of Safari?

    Monday, April 20, 2015 6:44 PM

Answers

  • User181 posted

    I'm not sure which crash you were originally seeing, but the crash that I saw (testing on iOS 8.3) was a thread consistency exception, which was caused by your code here:

        public override void PresentViewController(UIViewController viewControllerToPresent, bool animated, Action completionHandler)
        {
            DispatchQueue.DefaultGlobalQueue.DispatchAfter(new DispatchTime(DispatchTime.Now, NSEC_PER_USEC), () =>
                {
                    base.PresentViewController(viewControllerToPresent, animated, completionHandler);
                });
        }
    

    You can't call PresentViewController on a background thread, but that's what that code is trying. If I comment out that whole function then I get a popup when I tap the Choose button. Selecting an item in the popup did nothing, and it turns out that was because of this code:

        public override void DismissViewController(bool animated, Action completionHandler)
        {
    
        }
    

    That is causing the call to Dismiss (necessary to dismiss the popover and then present the modal camera view) to do nothing. Again, commenting out that code fixed the issue. With both of those methods entirely removed the example works fine for me.

    If you need to do the equivalent of the dispatch code to work around some crash that I'm not seeing then try this instead

        public override void PresentViewController(UIViewController viewControllerToPresent, bool animated, Action completionHandler)
        {
            NSTimer.CrreadScheduledTimer(0, timer =>
                {
                    base.PresentViewController(viewControllerToPresent, animated, completionHandler);
                });
        }
    
    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Monday, April 20, 2015 9:25 PM

All replies

  • User64419 posted

    Attached is a copy of my demo project that I've been messing around with. Feel free to pull it down and have a look.

    Monday, April 20, 2015 6:50 PM
  • User181 posted

    I'm not sure which crash you were originally seeing, but the crash that I saw (testing on iOS 8.3) was a thread consistency exception, which was caused by your code here:

        public override void PresentViewController(UIViewController viewControllerToPresent, bool animated, Action completionHandler)
        {
            DispatchQueue.DefaultGlobalQueue.DispatchAfter(new DispatchTime(DispatchTime.Now, NSEC_PER_USEC), () =>
                {
                    base.PresentViewController(viewControllerToPresent, animated, completionHandler);
                });
        }
    

    You can't call PresentViewController on a background thread, but that's what that code is trying. If I comment out that whole function then I get a popup when I tap the Choose button. Selecting an item in the popup did nothing, and it turns out that was because of this code:

        public override void DismissViewController(bool animated, Action completionHandler)
        {
    
        }
    

    That is causing the call to Dismiss (necessary to dismiss the popover and then present the modal camera view) to do nothing. Again, commenting out that code fixed the issue. With both of those methods entirely removed the example works fine for me.

    If you need to do the equivalent of the dispatch code to work around some crash that I'm not seeing then try this instead

        public override void PresentViewController(UIViewController viewControllerToPresent, bool animated, Action completionHandler)
        {
            NSTimer.CrreadScheduledTimer(0, timer =>
                {
                    base.PresentViewController(viewControllerToPresent, animated, completionHandler);
                });
        }
    
    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Monday, April 20, 2015 9:25 PM
  • User64419 posted

    Thanks @adamkemp, that seems to have resolved the issue in this test project. As you could probably tell by the simplicity and code commented out everywhere, this is just a test project to prototype out ideas. The code that you had me remove was due to some previous design and testing and I failed to clean up after myself in the project.

    Though I do not need the PresentViewController method in this project, that was a attempt at a work around for an iOS8 bug where if a user selects/taps on a drop-down menu in a UIWebView too quickly/often, then it will cause an unhandled exception and crash the application. I can't recall now what the exception is, but this was an attempted work around to restrain the WebView so that the order of Dismissing and Presenting the ViewController stayed in the correct order.

    Tuesday, April 21, 2015 11:47 AM
  • User181 posted

    If you can reproduce the original issue then try posting an example of that, and maybe I can suggest a better workaround.

    Tuesday, April 21, 2015 6:37 PM