Отказ от UIDocumentInteractionController в некоторых случаях приведет к удалению представлений контроллера представления в IOS 7 iPad

Когда UIDocumentInteractionController отклонен, представления контроллера представления представления удаляются, включая элементы из UINavigationController.

UIDocumentInteractionController отклоняет и представления контроллера представления представлений удаляются, оставляя простой бело-серый прямоугольник, в котором ранее существовал контроллер представления. Приложение больше не реагирует на любые сенсорные события после этой точки.

Это происходит на iPad Simulator (iOS 7.0) и iPad 3 (Wifi) под управлением iOS 7 для Quick Look Pdf Reader.

Не имеет значения, было ли приложение скомпилировано для iOS 6.1 или iOS 7 SDK

Пожалуйста, дайте мне знать ваши предложения.

3 ответа

У меня та же проблема, когда я представляю UIDocumentInteractionController из контроллера представления, представленного в виде листа модальной формы на iPad в iOS 7 (работал нормально в 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;
        }
    }
}

Я обнаружил, что ответ Майкла Кунтшера был точным. Небольшая модификация необходима, если UIDocumentInteractionController представлен из всплывающего окна.

Существует небольшая зависимость от иерархии представлений, которую можно устранить путем перебора родительских представлений, пока не будет найдено одно с суперпредставлением UIWindow. Кроме того, я обнаружил, что когда контроллер взаимодействия документов представлен из всплывающего окна, это немного разные представления, которые должны быть сохранены как parentView и containerView (в частности, мы хотим найти containerView так, чтобы его суперпредставление было UIPopoverView). Следующий фрагмент является переработанной версией ответа Майкла о включении этих изменений (обратите внимание, что 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 */
}

У меня была точно такая же проблема с приложением, зависшим в модальном представлении листа серой формы, которое потеряло все свое содержимое после того, как UIDocumentInteractionController был представлен и отклонен. Эти два решения здесь великолепны, но я упростил их для удовлетворения моего конкретного случая, который представлял собой UINavigationController внутри модального листа формы, который может представлять PDF в UIDocumentInteractionController, который я хотел использовать в качестве полноэкранного режима, а не помещать в контроллер навигации потому что область листа формы слишком мала для того, чтобы PDF можно было легко прочитать.

Я реализовал два метода UIDocumentInteractionControllerDelegate. Предположим следующее:

  • self.navController является ссылкой на UINavigationController, который представлен внутри модального листа.
  • в подклассе UIViewController объявлена ​​переменная-член @property (nonatomic, strong) UIView* docInteractionControllerWorkaroundSuperview;
  • SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO является #define за ([[[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 супервидение представления контроллера навигации теперь является UITransistionView. Но вскоре после этого (когда переход завершен), он устанавливается в ноль. Каким-то образом он отсоединился (или не был повторно присоединен) от UIDropShadowView. Сохраняя ссылку для просмотра этого при представлении UIDocumentInteractionController, мы можем подключить его вручную, и все работает нормально. Затем обязательно удалите ссылку, чтобы случайно не сохранить ее.

Этот метод не влияет на поведение в iOS 6 или любых предыдущих версиях iOS.

Другие вопросы по тегам