Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dismissing a UIDocumentInteractionController in some cases will remove the presenting view controller's views in IOS 7 iPad

When the UIDocumentInteractionController is dismissed, the presenting view controller's views are removed, including elements from the UINavigationController.

The UIDocumentInteractionController dismisses and the presenting view controller's views are removed, leaving a plain white/gray box where the presenting view controller formerly existed. The app no longer responds to any touch events after this point.

This Occurs on iPad Simulator (iOS 7.0) and iPad 3 (Wifi) running iOS 7 for Quick Look Pdf Reader.

Does not matter whether the application was compiled against the iOS 6.1 or iOS 7 SDK

Please let me know your suggestions.

like image 540
Gaurav Avatar asked Oct 19 '13 05:10

Gaurav


People also ask

How do you dismiss the presenting view controller?

When it comes time to dismiss a presented view controller, the preferred approach is to let the presenting view controller dismiss it. In other words, whenever possible, the same view controller that presented the view controller should also take responsibility for dismissing it.

What is a UIViewController?

The UIViewController class defines the shared behavior that's common to all view controllers. You rarely create instances of the UIViewController class directly. Instead, you subclass UIViewController and add the methods and properties needed to manage the view controller's view hierarchy.


2 Answers

I have this same problem when presenting a UIDocumentInteractionController from a view controller presented as a modal form sheet on iPad in iOS 7 (worked fine in iOS 6).

It looks like that during the transition from the document interaction controller back to the presenting view controller, the presenting view controller's view is wrapped in a temporary UITransitionView, and then that transition view is being removed from the view hierarchy after the transition is complete, along with the presenting view controller's view, leaving just UIDropShadowView that is the backing view of the modal form sheet visible (the gray box).

I worked around the problem by keeping a reference to my presenting view controller's root view (the one just before the drop shadow view in the hierarchy) when the document interaction controller preview will begin, and restoring that view to the hierarchy when the document interaction controller preview has ended.

Here's sample code:

    - (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;
        }
    }
}
like image 136
Michael Kuntscher Avatar answered Nov 16 '22 03:11

Michael Kuntscher


I found Michael Kuntscher answer to be right on target. A slight modification is necessary if the UIDocumentInteractionController is presented from a popover.

There is a slight dependence on the view hierarchy that can be eliminated by iterating over the parent views until one with a UIWindow superview is found. In addition, I found that when a document interaction controller is presented from within a popover it is slightly different views that need to be stored as the parentView and containerView (specifically we want to find a containerView such that its superview is a UIPopoverView). The following snippet is a re-worked version of Michael's answer to incorporate these changes (note that UIPopoverView is a private class, so we use string representations of the class rather than making a direct reference to each class):

- (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 */
}
like image 36
Amos Joshua Avatar answered Nov 16 '22 02:11

Amos Joshua