2014-09-19 61 views
34

我发现,编译iOS 8(并在iOS 8中运行)时,UIWebView无法显示相机/图像选择器,如果UIWebView位于视图控制器中模态。它在视图控制器中直接从窗口rootViewController或从其中推送的视图控制器“挂起”,没有问题。iOS 8 SDK:模态UIWebView和相机/图像选择器

测试应用程序可以在https://dl.dropboxusercontent.com/u/6214425/TestModalWebCamera.zip找到,但我会在下面描述它。我的测试应用程序(内置故事板,但实际应用程序不使用它们)有两个视图控制器(非原名为ViewControllerViewController2)。 ViewController包含在作为根视图控制器的UINavigationController中。 ViewController包含UIWebView(工作正常),“显示”(“推”)ViewController2和模式地呈现ViewController2的按钮。 ViewController2还有另一个UIWebView,它在“推”时起作用,但在“呈现”时不起作用。

两个ViewControllerViewController2装载有:

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    [self.webView loadHTMLString:@"<input type=\"file\" accept=\"image/*;capture=camera\">" baseURL:nil]; 
} 

当试图使用模式UIWebView的Xcode打印以下控制台或解散的应用模式:

Warning: Attempt to present <UIImagePickerController: 0x150ab800> on <ViewController2: 0x14623580> whose view is not in the window hierarchy! 

我目前的理论UIActionSheetUIAlertController的变化可能产生了这种情况,但这很难证明。以防万一,我会打开一个雷达与苹果,以防万一。

有人发现相同的情况和一些解决方法?

+1

目前处于同一条船上,尚未找到解决方法。我正在使用的应用程序在iOS 7中工作正常,但其行为与您在iOS 8中描述的相似。我在此问题上投入了一笔奖金,希望它能获得更多关注。 – bloudermilk 2014-09-22 18:08:15

+1

首先,输入文件在safari iOS 8中被破坏,它不会上传任何东西,这是一个错误,将在下次更新时修复。但我没有你的问题,我的应用程序只是当我点击输入文件按钮并选择类型(相机或照片库,它并不重要)崩溃 – jcesarmobile 2014-09-24 06:48:36

+1

同样在这里。当webview在作为Modal呈现的控制器内部时发生问题。我试图找出一个工作区。仍然适用于iOS 7,但不适用于iOS 8. – Marc 2014-09-24 21:12:45

回答

44

我发现在iOS 8.0.2中,iPad似乎没有那个缺陷,但iPhone仍然存在。

然而,压倒一切的视图控制器下面包含一个UIWebView

-(void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion 

并检查有一个presentedViewController似乎工作。

但需要检查的副作用

#import "UiWebViewVC.h" 

@interface UiWebViewVC() 

@property (weak, nonatomic) IBOutlet UIWebView *uiwebview; 

@end 

@implementation UiWebViewVC 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    NSURL *url = [NSURL URLWithString:@"http://html5demos.com/file-api-simple"]; 

    NSURLRequest *request = [NSURLRequest requestWithURL:url]; 

    self.uiwebview.scalesPageToFit = YES; 

    [self.uiwebview loadRequest:request]; 
} 


-(void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion 
{ 
    if (self.presentedViewController) 
    { 
     [super dismissViewControllerAnimated:flag completion:completion]; 
    } 
} 


@end 
+0

似乎是一个很好的解决方法。非常感谢你。我可以问一下你如何得到这个解决方案吗? – yonosoytu 2014-10-08 06:19:26

+6

uiwebview导致uialertcontroller被显示在uiwebviewviewcontroller上以显示相机/存在/取消。当用户选择选项时,uialertcontroller意味着被解散并且uuiimagepickercontroller被呈现。但是uialertcontroller的解散似乎会触发两次,第一次是可以的,因为shownviewcontroller = uialertcontroller,但是第二次presentationviewcontroller属性为零,并且这会导致dismissviewcontrolcontrolleranimated方法终止webviewviewcontroller,这是我的问题。现在测试这种情况 – seeinvisible 2014-10-08 07:06:32

+11

这解决了它对我来说。但记得呃,如果你在一个UINavigationController中展示你自定义的UIWebViewController(或者WKWebViewController),记住这个需要进去。因此,只需创建UINavigationController的子类并将其转储到那里。 – Baza207 2014-10-08 10:18:12

0

好的,这里是我最终使用的解决方法。这是一个2分钟的变化,相当黑客,但按预期工作,并避免我们都有的错误。基本上,我不是以模态方式呈现子视图控制器,而是将其设置为窗口的rootViewController并保留对父控制器的引用。那么,我曾经有过这样(在父视图控制器):

presentViewController(newController, animated: true, completion: nil) 

我现在有这个

view.window?.rootViewController = newController 

在这两种情况下,母公司控制器newController的代表,这是我怎么养参考资料。

newController.delegate = self 

最后,凡在我委托回调关闭模式,在那里我曾经有过这样的:

dismissViewControllerAnimated(true, completion: nil) 

我现在有这样的:

viewController.view.window?.rootViewController = self 

所以我们会得到相同的视图控制器完全接管屏幕的效果,然后在完成时进行控制。但在这种情况下,它不是动画。我有一种感觉动画控制器转换不会很难与一些内置的视图动画。

希望你已经在使用委托模式来管理与模式控制器的沟通,根据苹果的建议,但如果你不是,我相信你可以使用任意数量的方法来保存引用并回叫。

+0

上发现了这个问题,这是一个解决方法,你知道当视图是模态的时候有一个错误,然后你将它作为根视图控制器而不是模态地呈现它。但正如你所说,没有任何信息,如果你在iPad上,而你又不想全屏显示,那么你的解决方法是不可能的。你可以推视图控制器,你会有相同的效果,但与幻灯片动画 – jcesarmobile 2014-10-02 10:28:25

+0

@jcesarmobile是啊,不完全满意,但至少它让我们分发我们的应用程序。关于iPad的重点。我们只是iPhone,所以我没有考虑它。其实,我不知道这个bug是否发生在iPad上? – bloudermilk 2014-10-02 16:54:08

+0

这似乎并没有发生在Android上,但我遇到了这个问题在iOS 8.1与Xamarin,我没有设法编码您的解决方法xamarin :(。 – GabLeRoux 2014-11-14 03:45:25

1

我有一个类似的问题,我已经发现,在IOS的UIWebView的内容不支持HTML元素:

我不知道为什么苹果选择不支持这个重要的html元素,但我相信他们有他们的理由。 (尽管这个元素在iOS上的Safari上完美运行)。

在很多情况下,当用户在UIWebView中点击这种按钮时,它会让他们选择一张照片。但是,IOS中的UIWebView无法在提交表单时将这种文件附加到POST数据中。

解决方案:要完成相同的任务,您可以使用触发UIImagePickerController的按钮在InterfaceBuilder中创建一个类似的窗体。然后,您将创建一个包含所有表单数据和图像的HTTP POST请求。它并不像听起来那么难,请查看下面的链接,获取完成工作的一些示例代码:ios Upload Image and Text using HTTP POST

0

我的解决方案是使用基于控制器子级父级层次结构的自定义模态表示创建自定义视图控制器。动画将是相同的,所以用户不会注意到其中的差异。

我对动画的建议:

animateWithDuration:(animated ? 0.6 : 0.0) 
         delay:0.0 
    usingSpringWithDamping:1.f 
     initialSpringVelocity:0.6f 
        options:UIViewAnimationOptionCurveEaseOut 

它看起来酷似iOS7/8的默认模式的演示动画。

6

我有同样的问题在iOS 9尝试添加伊娃“_flag”,然后覆盖视图控制器这种方法有一个UIWebView

#pragma mark - Avoiding iOS bug 

- (UIViewController *)presentingViewController { 

    // Avoiding iOS bug. UIWebView with file input doesn't work in modal view controller 

    if (_flagged) { 
     return nil; 
    } else { 
     return [super presentingViewController]; 
    } 
} 

- (void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion { 

    // Avoiding iOS bug. UIWebView with file input doesn't work in modal view controller 

    if ([viewControllerToPresent isKindOfClass:[UIDocumentMenuViewController class]] 
    ||[viewControllerToPresent isKindOfClass:[UIImagePickerController class]]) { 
     _flagged = YES; 
    } 

    [super presentViewController:viewControllerToPresent animated:flag completion:completion]; 
} 

- (void)trueDismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion { 

    // Avoiding iOS bug. UIWebView with file input doesn't work in modal view controller 

    _flagged = NO; 
    [self dismissViewControllerAnimated:flag completion:completion]; 
} 

这工作对我罚款

+0

什么是'trueDismissViewController'?我应该在第一个视图控制器或模态视图控制器中添加它吗? – esh 2016-06-08 07:00:24

+0

'trueDismissViewControllerAnimated:completion:'当你需要关闭时,你应该在这个类中使用什么,而不是调用'dismissViewControllerAnimated:completion:'这将不起作用。 – 2017-04-13 14:29:53

1

对我来说,我更倾向于有一个自定义的UINavigationController,以便多个视图可以共享相同的逻辑。所以对于我的解决方法(在Swift中),这里是我放入我的自定义NavigationController。

import UIKit 

class NavigationController: UINavigationController { 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     // Dispose of any resources that can be recreated. 
    } 

    override func dismissViewControllerAnimated(flag: Bool, completion: (() -> Void)?) { 
     if let vc = self.presentedViewController { 
      // don't bother dismissing if the view controller being presented is a doc/image picker 
      if !vc.isKindOfClass(UIDocumentMenuViewController) || !vc.isKindOfClass(UIImagePickerController) { 
       super.dismissViewControllerAnimated(flag, completion:completion) 
      } 
     } 
    } 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     // make sure that the navigation controller can't be dismissed 
     self.view.window?.rootViewController = self 
    } 
} 

这意味着您可以使用webviews加载视图控制器,并且它们都可以使用文件上传元素。

+0

感谢它的工作 – mouness2020 2017-12-29 09:14:50

0

我每次在视图控制器发生变化时都做了什么,转换根目标视图。

从第一视图控制器:

let web = self.storyboard?.instantiateViewController(withIdentifier:"web") as! UINavigationController 

view.window?.rootViewController = web 

这是我通过根部到其他,当复出我在此第一个。

从网络视图控制器:

let first = self.storyboard?.instantiateViewController(withIdentifier: "reveal") as! SWRevealViewController 
    present(first, animated: true, completion: nil) 

,一切都很好,我可以显示从库中选择照片模式,拍照和一切。

我不知道这是否是一种很好的做法,但在仿真器和设备中工作正常。

希望它有帮助。