iOS 8 SDK:模态UIWebView和相机/图像select器
我发现,编译iOS 8(并在iOS 8中运行)时, UIWebView
无法显示相机/图像select器,如果UIWebView
在模态呈现的视图控制器中。 它可以在视图控制器中直接从窗口rootViewController
或从其中推送的视图控制器中“挂起”,而没有问题。
testing应用程序可以在https://dl.dropboxusercontent.com/u/6214425/TestModalWebCamera.zipfind,但我会在下面描述。
我的testing应用程序(用故事板构build,但真正的应用程序不使用它们)有两个视图控制器(非原名称的ViewController
和ViewController2
)。 ViewController
包含在作为根视图控制器的UINavigationController
中。 ViewController
包含一个UIWebView
(工作正常),一个“显示”(“推”)button和一个UIBarButtonItem
,它模态地呈现ViewController2
。 ViewController2
有另一个UIWebView
,当“推”,而不是“呈现”时,工作。
ViewController
和ViewController2
都加载了:
- (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!
我目前的理论是, UIActionSheet
到UIAlertController
的变化可能产生了这种情况,但是很难certificate。 以防万一,我会打开雷达与苹果,以防万一。
有人发现相同的情况和一些解决方法?
我发现,在iOS 8.0.2 iPad似乎没有这个错误,但iPhone仍然如此。
但是,在包含uiwebview的视图控制器中重写以下内容
-(void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion
并检查有一个presentViewController似乎工作。
但是需要检查副作用
#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
我有同样的问题在iOS 9上。尝试添加ivar'_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]; }
这对我很好
我有一个类似的问题,我发现IOS中的UIWebView元素不支持html元素:
我不知道为什么苹果select不支持这个重要的html元素,但我相信他们有他们的理由。 (即使这个元素在IOS上的Safari上完美工作。)
在很多情况下,当用户在UIWebView中点击这种button时,会让他们select一张照片。 但是,IOS中的UIWebView不具备在提交表单时将此类文件附加到POST数据中的function。
解决scheme:要完成相同的任务,您可以使用触发UIImagePickerController的button在InterfaceBuilder中创build一个类似的窗体。 然后,您将创build一个包含所有表单数据和图像的HTTP POST请求。 这不像听起来那么难,请查看下面的链接,获取完成任务的示例代码: ios使用HTTP POST上传图像和文本
好的,这是我最终使用的解决方法。 这是一个2分钟的变化,很hacky,但按预期工作,并避免了我们所有的错误。 基本上,而不是模态地呈现子视图控制器,我将其设置到窗口的rootViewController并保持对父控制器的引用。 所以,我曾经有过(在父视图控制器):
presentViewController(newController, animated: true, completion: nil)
我现在有这个
view.window?.rootViewController = newController
在这两种情况下,父控制器是newController
的委托,这是我如何保持参考。
newController.delegate = self
最后,在我的委托closures模式的地方,我曾经有过这样的地方:
dismissViewControllerAnimated(true, completion: nil)
我现在有这个:
viewController.view.window?.rootViewController = self
所以我们得到了一个视图控制器完全接pipe屏幕的效果,然后在完成时产生控制。 在这种情况下,它不是animation。 我有一个感觉animation控制器转换不会很难与一些内置的视图animation。
希望你已经在使用委托模式来pipe理与模式控制器的通信,根据苹果的build议,但如果你不是,我相信你可以使用任何数量的方法来保存参考和回叫。
我的解决scheme是创build自定义视图控制器与基于控制器子级父级层次结构的自定义模态演示。 animation将是相同的,所以用户不会注意到不同之处。
我对animation的build议:
animateWithDuration:(animated ? 0.6 : 0.0) delay:0.0 usingSpringWithDamping:1.f initialSpringVelocity:0.6f options:UIViewAnimationOptionCurveEaseOut
它将看起来像iOS7 / 8中的默认模态演示animation。
对我来说,我倾向于有一个自定义的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加载视图控制器,并且它们都可以使用file upload元素。
每当视图控制器发生变化时,我都做了什么,转换根目录视图。
从第一个视图控制器:
let web = self.storyboard?.instantiateViewController(withIdentifier:"web") as! UINavigationController view.window?.rootViewController = web
这是我如何传递根源到另一个,当回到第一个我做到这一点。
从networking视图控制器:
let first = self.storyboard?.instantiateViewController(withIdentifier: "reveal") as! SWRevealViewController present(first, animated: true, completion: nil)
一切都很好,我可以显示从图书馆select照片的模式,拍照和其他一切。
我不知道这是否是一个好的做法,但在仿真器和设备中工作正常。
希望它有帮助。