我发现,在编译iOS 8(并在iOS 8中运行)时,UIWebView
如果UIWebView
位于模态显示的视图控制器中,则无法显示相机/图像选择器。它在视图控制器中直接从窗口rootViewController
“悬挂”或从中推出视图控制器时没有问题。
测试应用程序可以在https://dl.dropboxusercontent.com/u/6214425/TestModalWebCamera.zip找到,但我将在下面对其进行描述。
我的测试应用程序(使用故事板构建,但实际应用程序不使用它们)有两个视图控制器(非原始名称为ViewController
和ViewController2
)。 ViewController
包含在UINavigationController
中,它是根视图控制器。 ViewController
包含UIWebView
(工作正常),“显示”(“推送”)ViewController2
的按钮,以及模态显示UIBarButtonItem
的{{1}}。 ViewController2
有另一个ViewController2
,在“推送”时有效,但在“呈现”时无效。
UIWebView
和ViewController
都加载了:
ViewController2
尝试使用模态- (void)viewDidLoad {
[super viewDidLoad];
[self.webView loadHTMLString:@"<input type=\"file\" accept=\"image/*;capture=camera\">" baseURL:nil];
}
Xcode在控制台中打印以下内容并解除应用模式:
UIWebView
我目前的理论是,Warning: Attempt to present <UIImagePickerController: 0x150ab800> on <ViewController2: 0x14623580> whose view is not in the window hierarchy!
到UIActionSheet
的变化可能会产生这种情况,但很难证明。我将与Apple一起打开雷达,以防万一。
有人发现了相同的情况和一些解决方法吗?
答案 0 :(得分:46)
我发现在iOS 8.0.2中iPad似乎没有那个bug,但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
答案 1 :(得分:7)
我在iOS 9上遇到同样的问题。尝试添加ivar&#39; _flag&#39;然后使用UIWebView
在视图控制器中覆盖此方法knitr
这对我很有用
答案 2 :(得分:2)
对我来说,我倾向于使用自定义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
}
}
这意味着你可以拥有大量带有webview的视图控制器,并且它们都可以使用文件上传元素。
答案 3 :(得分:1)
我遇到了类似的问题,我发现IOS中的UIWebView元素不支持html元素:
我不确定为什么Apple选择不支持这个重要的html元素,但我相信他们有他们的理由。 (即使这个元素在IOS上的Safari上完美运行。)
在许多情况下,当用户在UIWebView中单击此类按钮时,它将允许他们拍摄/选择照片。但是,IOS中的UIWebView无法在提交表单时将这样的文件附加到POST数据中。
解决方案:要完成相同的任务,您可以使用触发UIImagePickerController的按钮在InterfaceBuilder中创建类似的表单。然后,您创建一个包含所有表单数据和图像的HTTP POST请求。它并不像听起来那么难,请查看下面的链接,了解完成工作的示例代码:ios Upload Image and Text using HTTP POST
答案 4 :(得分:0)
好的,这是我最终使用的解决方法。这是一个2分钟的变化,非常hacky,但按预期工作,避免我们都有的错误。基本上,我不是以模态方式呈现子视图控制器,而是将其设置为窗口的rootViewController并保留对父控制器的引用。所以我以前在这里(在父视图控制器中):
presentViewController(newController, animated: true, completion: nil)
我现在有了这个
view.window?.rootViewController = newController
在这两种情况下,父控制器都是newController
的委托,这就是我保留引用的方式。
newController.delegate = self
最后,在我的委托回调中关闭模态的地方,我曾经有过这个:
dismissViewControllerAnimated(true, completion: nil)
我现在有了这个:
viewController.view.window?.rootViewController = self
因此我们得到了视图控制器完全接管屏幕的相同效果,然后在完成时产生控制权。但在这种情况下,它不是动画。我有一种感觉动画控制器过渡对于一些内置的视图动画不会很难。
根据Apple的建议,希望您已经使用委托模式来管理与模态控制器的通信,但如果您不是,我确定您可以使用任意数量的方法来保留引用并回复。
答案 5 :(得分:0)
我的解决方案是使用基于控制器子父级层次结构的自定义模式演示创建自定义View Controller。动画将是相同的,因此用户不会注意到差异。
我对动画的建议:
animateWithDuration:(animated ? 0.6 : 0.0)
delay:0.0
usingSpringWithDamping:1.f
initialSpringVelocity:0.6f
options:UIViewAnimationOptionCurveEaseOut
它看起来与iOS7 / 8中的默认模态演示动画完全相同。
答案 6 :(得分: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)
一切都很好,我可以显示从库中选择照片的模式,拍照和其他所有内容。
我不知道这是不是一个好习惯,但在模拟器和设备上工作正常。
希望它有所帮助。