美文网首页
模态UIViewController中WebView的H5弹出C

模态UIViewController中WebView的H5弹出C

作者: pigLily | 来源:发表于2018-09-05 22:42 被阅读0次

    关于present页面,且UIViewController中WebView的H5弹出Camera/ImagePicker大致分3种情况,严格意义上是分2种情况:
    1.一个ViewController A present ViewController D
    2.把ViewController B放到一个UINavigationController中管理,ViewController A present ViewController B,ViewController B present ViewController D
    3.把ViewController B放到一个UINavigationController中管理,ViewController A present这个UINavigationController,B push ViewController C,C push ViewController D

    ViewController D中有一个UIWebView,加载h5页面,h5页面有个按钮调用手机的相机、相册UIImagePickerController,弹出了拍照,相册选择的UIActionSheet, 然后点击相机、相册按钮,第一种问题会直接退到A页面,第二种情况会退出到B页面,第三种情况会直接退出到A页面。

    最简单的解决方案就是:所有流程都采用push页面的方式,这样的话,在点击相机、相册后会回到系统相册里面,选择后会回到h5页面。
    如果项目采用present页面流程已经完善,后面版本涉及到调用h5弹出Camera/ImagePicker,此时在修改弹出页面的方式为push会带来很大工作量,如何解决仍然采用present方式也能实现h5调用相机、相册呢?

    问题出现的原因:
    点击h5按钮,会弹出UIActionSheet框,如下图所示,


    D7C2E385D6D2873598ECFB93DA5E22F3.jpg

    点击UIActionSheet中item => UIActionSheet dismiss => 弹出相机或者ImagePicker => 拍照或者选择图片后弹出相机或者ImagePicker dismiss

    分析下问题:
    UIActionSheet有可能是被当前ViewController D执行presentViewController模态出来的。也有可能是被D的parentViewControler(或者是UINavgationControler了)模态出来的,验证猜想很简单,在ViewController D,UINavgationControler子类或者类别,重写如下方法即可。


    7A674912D124F92F4C6836B246E74866.jpg

    可以查看控制台上打印的viewControllerToPresent的值,发现并不是UIActionSheet,而是我们很少使用的UIDocumentMenuViewController。
    一个presentedViewController要dismiss的时候会调用presentingViewController的如下方法,所以重写ViewController D中dismissViewControllerAnimated
    -(void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion
    {
    }
    断点后发现,dismissViewControllerAnimated执行了两次,问题现象就是,dimiss掉了所有的modal试图,那么好了,问题找到了,UIDocumentMenuViewController关闭后不仅调用了自己的,dismissViewControllerAnimated,还调用了,上层或者上上层presentingViewController的dismissViewControllerAnimated
    知道问题的原因就比较好找解决方案了:
    1.使dismissViewControllerAnimated只调用一次
    当前ViewController 的所有presentedViewController都正常执dismissViewControllerAnimated,当前ViewController本身执行dismissViewControllerAnimated,不进行dismiss,不做处理。
    -(void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion
    {
    if (self.presentedViewController)
    {
    [super dismissViewControllerAnimated:flag completion:completion];
    }
    }
    这样当前ViewController不会调用重写的dismissViewControllerAnimated。

    2.使UIDocumentMenuViewController找不到presentingViewController
    断点后发调用

    • (void)presentViewController:(UIViewController )viewControllerToPresent animated:(BOOL)flag
      弹出UIDocumentMenuViewController之后,又调用了- (UIViewController
      )presentingViewController返回的presentingViewController是上一个页面。
      苹果的特性:当模态出N个ViewController后,只需要dismiss任意一个,都会dismiss它之后所有的模态视图。
      那就可以不让UIDocumentMenuViewController找到上层或上上层的任意presentingViewController
    • (UIViewController *)presentingViewController
      {
      if (_flag) {
      return nil;
      } else {
      return [super presentingViewController];
      }
      }
    • (void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion
      {
      NSLog(@"viewControllerToPresent:%@",viewControllerToPresent);
      if ([viewControllerToPresent isKindOfClass:[UIDocumentMenuViewController class]] || [viewControllerToPresent isKindOfClass:[UIImagePickerController class]]) {
      _flag = YES;
      }
      [super presentViewController:viewControllerToPresent animated:flag completion:completion];
      }

    总之,上面2个方法可以根据自己项目的特征写在最后一个被present的ViewController里,或者UINavigationController类别里。
    附demo链接:https://github.com/wangxaioli/Present
    被UINavigationController管理的demo:https://github.com/wangxaioli/Push

    相关文章

      网友评论

          本文标题:模态UIViewController中WebView的H5弹出C

          本文链接:https://www.haomeiwen.com/subject/iflzwftx.html