10

当 UIDocumentInteractionController 被解除时,呈现视图控制器的视图被移除,包括来自 UINavigationController 的元素。

UIDocumentInteractionController 关闭并且呈现视图控制器的视图被删除,在呈现视图控制器以前存在的地方留下一个纯白色/灰色框。在此之后,应用程序不再响应任何触摸事件。

这发生在运行 iOS 7 的 iPad 模拟器 (iOS 7.0) 和 iPad 3 (Wifi) 上,用于快速查看 PDF 阅读器。

无论应用程序是针对 iOS 6.1 还是 iOS 7 SDK 编译的

请让我知道你的建议。

4

3 回答 3

4

在 iOS 7(在 iOS 6 中运行良好)中,在 iPad 上作为模式表单呈现的视图控制器中呈现 UIDocumentInteractionController 时,我遇到了同样的问题。

看起来在从文档交互控制器转换回呈现视图控制器的过程中,呈现视图控制器的视图被包装在一个临时的 UITransitionView 中,然后在转换完成后,该转换视图被从视图层次结构中删除,沿着使用呈现视图控制器的视图,只留下 UIDropShadowView,它是可见的模态表单的支持视图(灰色框)。

当文档交互控制器预览将开始时,我通过保留对呈现视图控制器的根视图(层次结构中阴影视图之前的那个)的引用来解决该问题,并在文档交互控制器开始时将该视图恢复到层次结构预览已结束。

这是示例代码:

    - (void)documentInteractionControllerWillBeginPreview:(__unused UIDocumentInteractionController *)controller {

    if (UIUserInterfaceIdiomPad == UI_USER_INTERFACE_IDIOM()) {
        // work around iOS 7 bug on ipad

        self.parentView = [[[self.view superview] superview] superview];
        self.containerView = [self.parentView superview];

        if (![[self.containerView superview] isKindOfClass: [UIWindow class]]) {
            // our assumption about the view hierarchy is broken, abort
            self.containerView = nil;
            self.parentView = nil;
        }
    }
}

    - (void)documentInteractionControllerDidEndPreview:(__unused UIDocumentInteractionController *)controller {

    if (UIUserInterfaceIdiomPad == UI_USER_INTERFACE_IDIOM()) {
        if (!self.view.window && self.containerView) {
            assert(self.parentView);
            CGRect frame = self.parentView.frame;
            frame.origin = CGPointZero;
            self.parentView.frame = frame;
            [self.containerView addSubview: self.parentView];
            self.containerView = nil;
            self.parentView = nil;
        }
    }
}
于 2013-11-13T14:22:28.747 回答
2

我发现 Michael Kuntscher 的答案是正确的。如果 UIDocumentInteractionController 是从弹出窗口中显示的,则需要稍作修改。

对视图层次结构有轻微的依赖性,可以通过遍历父视图来消除这种依赖性,直到找到具有 UIWindow 父视图的视图。此外,我发现当一个文档交互控制器从一个弹出窗口中呈现时,需要存储为父视图和容器视图的视图略有不同(具体来说,我们希望找到一个容器视图,使其超级视图是 UIPopoverView)。下面的代码片段是 Michael 的回答的重新处理版本,用于合并这些更改(请注意 UIPopoverView 是一个私有类,因此我们使用该类的字符串表示,而不是直接引用每个类):

- (void)documentInteractionControllerWillBeginPreview:(UIDocumentInteractionController *)controller {

    /* iOS 7 DIC bug workaround  */
    if (UIUserInterfaceIdiomPad == UI_USER_INTERFACE_IDIOM()) {
        UIView *a_view = self.view;

        self.dicParentView = nil;
        self.dicContainerView = nil;

        while (a_view != nil) {
            UIView *super_super_view = [[a_view superview] superview];
            NSString *str_class = NSStringFromClass([super_super_view class]);

            if ([str_class isEqualToString:@"UIWindow"] ||
                [str_class hasSuffix:@"PopoverView"]) {
                self.dicParentView = a_view;
                self.dicContainerView = [a_view superview];
                break;
            }
            a_view = [a_view superview];
        }

        if (self.dicParentView == nil) {
            NSLog(@"Could not appropriate superview, unable to workaround DIC bug");
        }
    }
    /* end work around */
}

- (void)documentInteractionControllerDidEndPreview:(__unused UIDocumentInteractionController *)controller {
    /* iOS 7 DIC bug workaround */
    if (UIUserInterfaceIdiomPad == UI_USER_INTERFACE_IDIOM()) {
        if ((self.view.window == nil) &&
            (self.dicContainerView != nil) &&
            (self.dicParentView != nil)) {
            NSLog(@"Restoring view for DIC presenter in the view hierarchy");
            CGRect frame = self.dicParentView.frame;
            frame.origin = CGPointZero;
            self.dicParentView.frame = frame;
            [self.dicContainerView addSubview: self.dicParentView];
            self.dicContainerView = nil;
            self.dicParentView = nil;
        }
    }
    /* end work around */
}
于 2013-12-11T16:09:21.987 回答
0

在呈现和关闭 UIDocumentInteractionController 后,应用程序停止在灰色表单模式视图上丢失了所有内容,我遇到了完全相同的问题。这里的两个解决方案很棒,但我简化了它们以适应我的特殊情况,它是表单模式中的 UINavigationController,可以在 UIDocumentInteractionController 中呈现 PDF,我希望它是全屏模式而不是在导航控制器中推送因为表单区域太小,PDF 难以阅读。

我实现了两个 UIDocumentInteractionControllerDelegate 方法。假设如下:

  • self.navController是对 UINavigationController 的引用,显示在表单模式中。
  • 在 UIViewController 子类中声明了一个成员变量@property (nonatomic, strong) UIView* docInteractionControllerWorkaroundSuperview;
  • #defineSYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO是([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)

首先:

-(UIViewController*)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController*)controller
{    
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0") && self.navigationController.modalPresentationStyle == UIModalPresentationFormSheet)
    {
        self.docInteractionControllerWorkaroundSuperview = [self.navigationController.view superview];
    }
    return self.navigationController.visibleViewController;
}

然后:

- (void)documentInteractionControllerDidEndPreview:(UIDocumentInteractionController *)controller
{
    if (self.docInteractionControllerWorkaroundSuperview != nil)
    {
        NSLog(@"Workaround iOS 7 document interaction bug... resetting nav controller view into modal");

        //reset the nav controller view from whence it came.
        self.navigationController.view.frame = CGRectMake(0.0, 0.0, self.navigationController.view.frame.size.width, self.navigationController.view.frame.size.height);
        [self.docInteractionControllerWorkaroundSuperview addSubview:self.navigationController.view];

        self.docInteractionControllerWorkaroundSuperview = nil;
    }
}

即在呈现 UIDocumentInteractionController 时,查看导航控制器视图的超级视图。它是一个 UIDropShadowView,我假设它是表单模式的部分透明灰色/黑色背景,它使呈现模式的后面的视图变暗。

当 PDF 被关闭时,documentInteractionControllerDidEndPreview导航控制器视图的超级视图中现在是 UITransitionView。但是在那之后不久(当转换完成时),它被设置为 nil。不知何故,它与 UIDropShadowView 分离(或没有重新连接)。通过在呈现 UIDocumentInteractionController 时保留对视图的引用,我们可以手动重新附加它,一切正常。然后确保取消引用以确保我们不会意外保留它。

此方法不会影响 iOS 6 或任何以前的 iOS 版本上的行为。

于 2014-02-25T05:56:19.273 回答