在某些情况下解除UIDocumentInteractionController将删除IOS 7 iPad中呈现视图控制器的视图

时间:2013-10-19 05:26:30

标签: iphone objective-c ipad ios7 ipad-3

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

UIDocumentInteractionController解除并移除呈现视图控制器的视图,留下一个纯白色/灰色框,其中呈现视图控制器以前存在。在此之后,应用程序不再响应任何触摸事件。

在运行iOS 7 for Quick Look Pdf Reader的iPad模拟器(iOS 7.0)和iPad 3(Wifi)上发生这种情况。

应用程序是否针对iOS 6.1或iOS 7 SDK进行编译无关紧要

请告诉我你的建议。

3 个答案:

答案 0 :(得分:4)

我在iOS 7的iPad上以视图控制器的形式呈现UIDocumentInteractionController时遇到同样的问题(在iOS 6中运行良好)。

看起来在从文档交互控制器转换回呈现视图控制器期间,呈现视图控制器的视图被包装在临时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;
        }
    }
}

答案 1 :(得分:2)

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

视图层次结构略有依赖,可以通过迭代父视图来消除,直到找到具有UIWindow超级视图的视图。另外,我发现当从popover中呈现文档交互控制器时,需要存储为parentView和containerView的略有不同的视图(特别是我们想要找到一个容器视图,使得它的superview是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 */
}

答案 2 :(得分:0)

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

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

  • self.navController是对表单模式中显示的UINavigationController的引用。
  • 在UIViewController子类@property (nonatomic, strong) UIView* docInteractionControllerWorkaroundSuperview;
  • 中声明了一个成员变量
  • SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO是#define的{​​{1}}

首先:

([[[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;
}

即。在展示UIDocumentInteractionController时,请查看导航控制器视图的超级视图。它可以说是一个UIDropShadowView,我假设它是表单模态的部分透明的灰色/黑色背景,它模糊了显示模态背后的视图。

当PDF被解雇时,在- (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; } } 中,导航控制器视图的超级视图现在是UITransistionView。但在那之后不久(转换完成时),它被设置为零。不知怎的,它从UIDropShadowView分离(或没有重新附加)。通过在呈现UIDocumentInteractionController时保持引用来查看它,我们可以手动重新附加它,一切正常。然后一定要把参考文件弄清楚,以确保我们不会意外地保留它。

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