«Из контроллера представления» исчезает с помощью UIViewControllerContextTransitioning


105

У меня возникла одна проблема, и я описал ее ниже.

Я использую UIViewControllerContextTransitioning для пользовательских переходов.

У меня есть 2 контроллера представления, контроллер первого представления и контроллер второго представления.

Теперь я хочу добавить второй контроллер представления к контроллеру первого представления с анимацией. Я добился этого, теперь второй контроллер представления прозрачен, поэтому мы можем видеть первый контроллер представления ниже второго контроллера представления.

Но я не могу видеть контроллер первого представления, и я вижу только черный экран под контроллером второго представления.

-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{
    self.transitionContext = transitionContext;
    if(self.isPresenting){
        [self executePresentationAnimation:transitionContext];
    }
    else{
       [self executeDismissalAnimation:transitionContext];
    }
  }

-(void)executePresentationAnimation:(id<UIViewControllerContextTransitioning>)transitionContext{
     UIView* inView = [transitionContext containerView];
     UIViewController* toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

     UIViewController* fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];

     CGRect offScreenFrame = inView.frame;
     offScreenFrame.origin.y = inView.frame.size.height;
     toViewController.view.frame = offScreenFrame;

    toViewController.view.backgroundColor = [UIColor clearColor];
    fromViewController.view.backgroundColor = [UIColor clearColor];
    inView.backgroundColor = [UIColor  clearColor];
    [inView insertSubview:toViewController.view aboveSubview:fromViewController.view];
     // [inView addSubview:toViewController.view];
    CFTimeInterval duration = self.presentationDuration;
    CFTimeInterval halfDuration = duration/2;

    CATransform3D t1 = [self firstTransform];
    CATransform3D t2 = [self secondTransformWithView:fromViewController.view];

    [UIView animateKeyframesWithDuration:halfDuration delay:0.0 options:UIViewKeyframeAnimationOptionCalculationModeLinear animations:^{

    [UIView addKeyframeWithRelativeStartTime:0.0f relativeDuration:0.5f animations:^{
        fromViewController.view.layer.transform = t1;
    }];

    [UIView addKeyframeWithRelativeStartTime:0.5f relativeDuration:0.5f animations:^{
        fromViewController.view.layer.transform = t2;
    }];
    } completion:^(BOOL finished) {
    }];


    [UIView animateWithDuration:duration delay:(halfDuration - (0.3*halfDuration)) usingSpringWithDamping:0.7f initialSpringVelocity:6.0f options:UIViewAnimationOptionCurveEaseIn animations:^{
        toViewController.view.frame = inView.frame;
    } completion:^(BOOL finished) {
        [self.transitionContext completeTransition:YES];
    }];
}

При [self.transitionContext completeTransition:YES];вызове первый контроллер представления внезапно исчезает, а под контроллером второго представления отображается черный экран.

Есть ли у кого-нибудь идеи? Спасибо.

Ответы:


98

У меня была такая же проблема - похоже, ошибка в iOS 8. Я подал радар .

Я использовал Reveal для проверки иерархии представлений после того, как экран погас. Ключ UIWindowполностью пустой - никакой иерархии представлений!

Раскрыл

Я немного поигрался, и похоже, что для простых случаев есть простой обходной путь. Вы можете просто повторно добавить представление toViewController'в качестве подвида ключевого окна:

transitionContext.completeTransition(true)
UIApplication.sharedApplication().keyWindow!.addSubview(toViewController.view)

Я проверил, и ключевое окно по- rootViewControllerпрежнему настроено правильно, так что все в порядке. Я не уверен, что произойдет, если вы представите свой контроллер из уже представленного модального контроллера, поэтому для более сложных случаев вам придется поэкспериментировать.


2
Я тоже видел эту проблему. iOS 8 представляет новый метод и ключи для доступа к fromView и toView (Примечание: не контроллер представления) Похоже, что эти ссылки не теряются во время перехода. Вы можете добавить их в представление контейнера, как обычно, если бы вы только что получили их из контроллеров представления.
тапи

1
Я наблюдал аналогичные странности iOS 8 при попытке добавить подпредставления к представлению моего контроллера навигации в viewDidLoad. Повторное добавление представления navigationController к keyWindow, похоже, помогло, большое спасибо, Эш!
taber 09

1
Я все еще вижу это в GM (и это исправление все еще работает). Другие видят то же самое? Это просто изменение API?
rjkaplan

21
Я обнаружил, что эта ошибка (и многие другие!) Исчезают, если вы установите ее modalPresentationStyle = UIModalPresentationFullScreen. Вы, конечно, по-прежнему получаете собственную анимацию перехода.
Крис

1
Спасибо @AshFurrow. Хороший обходной путь, пока он не будет исправлен!
kandelvijaya

78

Я считаю, что следует лучше объяснить причину этого.

Представление исчезает, потому что вы извлекаете представление контроллера представления представления из его исходного местоположения (иерархии представлений), помещаете его в containerView, который предоставляет ваш аниматор, но никогда не возвращает его обратно после завершения анимации. Таким образом, представление контроллера представления полностью удалено с его супервизором (containerView) из окна.

В iOS 7 система всегда возвращала представления контроллеров представлений, которые участвуют в презентации (представляются и представляются), на их исходные места после того, как переход завершает анимацию автоматически. Этого больше не происходит с некоторыми стилями представления в iOS 8.

Правило очень простое: аниматор должен манипулировать представлением контроллера представления только в том случае, если представление этого контроллера представления будет полностью скрыто (удалено из иерархии представлений) к концу перехода . Другими словами, это означает, что после завершения начальной анимации презентации будет видно только представление представленного контроллера представления, а не представление контроллера представления представления. Например, если вы установите непрозрачность представления представленного контроллера представления на 50% и используете UIModalPresentationFullScreen, вы не сможете увидеть представление представления контроллера представления под представленным, но если вы используете UIModalPresentationOverFullscreen - вы будете (UIPresentationController'sshouldRemovePresentersView за указание этого отвечает метод ).

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

В iOS 8 viewForKey:был введен метод получения представлений, которыми манипулирует аниматор. Во-первых, это помогает следовать описанному выше правилу, возвращая nil всякий раз, когда аниматор не должен касаться вида. Во-вторых, аниматор может возвращать другой вид для анимации. Представьте, что вы реализуете презентацию, похожую на лист формы. В этом случае вам нужно добавить тень или украшение вокруг представленного представления контроллера представления. Аниматор вместо этого анимирует это украшение, и представленное представление контроллера представления будет дочерним для этого украшения.

viewControllerForKey: не исчезает, его все еще можно использовать, если требуется прямой доступ к контроллерам представлений, но аниматор не должен делать никаких предположений относительно представлений, которые ему нужно анимировать.

Есть несколько вещей, которые вы можете сделать, чтобы правильно исправить проблему с исчезающим представлением представления контроллера представления, когда вы явно помещаете его в представление контейнера аниматора:

  1. Если не нужно анимировать представление контроллера представления представления, используйте, viewForKey:чтобы получить представления для анимации вместо того, чтобы обращаться к представлениям контроллера напрямую. viewForKey:может возвращать ноль или даже совершенно разные представления.

  2. Если вы хотите анимировать представление контроллеров представления представления, вам следует рассмотреть возможность использования UIModalPresentationFullScreenстиля или продолжить использование UIModalPresentationCustomи реализовать свой собственный подкласс UIPresentationController с shouldRemovePresentersViewвозвратом YES. На самом деле, реализация этого метода является то, основное различием между внутренними контроллерами представления , определенных UIModalPresentationFullScreenи UIModalPresentationCustomстилями , кроме того факта , что последние позволяют использовать контроллеры пользовательских представлений.

  3. Во всех других редких случаях вам придется вернуть представление контроллера представления в исходное местоположение, как предлагали другие ответы.


2
Это супер-странно , потому что этот код использует viewControllerForKey:«ы views только когда viewForKey:возвращается NIL, и я все еще должен был повторно добавить его в окно вручную. У вас есть пример кода, работающего без этого обходного пути?
Ash Furrow

Что ж, если viewForKey:возвращается nil, тогда вам наверняка придется повторно добавить представление контроллера представления представления в окно, если вы удалите его из него в своем аниматоре. В случае, если viewForKey возвращает фактическое представление контроллера представления, можно безопасно переместить это представление, поскольку UIKit вернет его в исходное положение после завершения жизненного цикла презентации.
egdmitry

Спасибо, что объяснили причину этой проблемы. Ты совершенно прав. Перемещение позиции представления в иерархии представлений без его замены, очевидно, приведет к его исчезновению (опубликовать iOS 8, и я работаю с iOS 10 прямо сейчас!) Спасибо за пояснение.
Clay Ellis

1
Спасибо egdmitry за ваше разъяснение. Какой поднять другой вопрос: как вы думаете , я должен реализовать выявить как презентации? Один из тех, которые очень распространены в настоящее время, когда представление представления частично выдвигается, чтобы показать представленное представление внизу? В этом сценарии и представление, и представление должны быть на экране, а представление представления является анимированным.
Андреа

70

В iOS 8 вы должны манипулировать представлениями, возвращаемыми, viewForKey:вместо .viewсвойств контроллеров представлений, возвращаемых viewControllerForKey:. Это не особо ясно из документации по бета-версии, но если вы посмотрите исходный код UIViewControllerTransitioning.h, вы увидите этот комментарий выше viewControllerForKey::

// Currently only two keys are defined by the
// system - UITransitionContextToViewControllerKey, and
// UITransitionContextFromViewControllerKey.
// Animators should not directly manipulate a view controller's views and should
// use viewForKey: to get views instead.
- (UIViewController *)viewControllerForKey:(NSString *)key;

Поэтому вместо настройки кадров и т. Д. toViewController.viewИспользуйте возвращаемое значение [transitionContext viewForKey:UITransitionContextToViewKey].

Если ваше приложение должно поддерживать iOS7 и / или Xcode 5, вы можете использовать простой метод категорий в UIViewController, например:

- (UIView *)viewForTransitionContext:(id<UIViewControllerContextTransitioning>)transitionContext
{
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
    if ([transitionContext respondsToSelector:@selector(viewForKey:)]) {
        NSString *key = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey] == self ? UITransitionContextFromViewKey : UITransitionContextToViewKey;
        return [transitionContext viewForKey:key];
    } else {
        return self.view;
    }
#else
    return self.view;
#endif
}

Затем получите toViewControllerи, fromViewControllerкак обычно, но используйте представления [toViewController viewForTransitionContext:transitionContext].

Изменить: похоже, есть ошибка, при которой представление контроллера представления представления равно нулю при возврате из viewForKey, что не позволяет вам делать модальные переходы, которые вообще анимируют представление представления (например, скольжение или горизонтальное переключение). Я зарегистрировал ошибку для iOS8 на rdar: // 17961976 ( http://openradar.appspot.com/radar?id=5210815787433984 ). Также см. Образец проекта на http://github.com/bcherry/TransitionBug

Изменить 2: Спасибо graveley за предложение, использование UIModalPresentationFullScreen устраняет проблему. Возможно, это не ошибка. Apple может предполагать, что UIModalPresentationCustom изменяет только вид входящего модального окна. Если вы хотите изменить исходящее представление, вам нужно гарантировать полноэкранное представление нового представления? В любом случае следует использовать viewForKeyи UIModalPresentationFullScreen.


2
Ошибка viewForKey сводила меня с ума! - спасибо за подачу. FWIW мой переход работает нормально, получая представление из UITransitionContextToViewControllerKey, но мой переход применяет преобразование только ко всему представлению. Я не уверен, следует ли это интерпретировать как manipulatingвзгляды венчурных капиталистов или нет ...
MathewS,

1
Вау - это безумие. Я не видел этого в различиях - вероятно, потому что это просто небольшой комментарий. Действительно неприятно, когда Apple делает такой трюк. Скрестим пальцы по поводу вашего радара.
Ash Furrow

Я тоже вижу viewForKeyошибку в GM. Другие тоже? Вы нашли разумное решение?
rjkaplan

2
Я думал, что в соответствии с комментарием - viewForKey// viewForKey: может вернуть nil, что указывало бы на то, что аниматор не должен манипулировать представлением связанного контроллера представления. Возврат nilне является ошибкой.
Кен Куан

4
@kenKuan, возможно, ты прав. при использовании UIModalPresentationFullScreen viewForKeyвозвращает из представления и для просмотра. Так что, возможно, он намеренно возвращает nil для UIModalPresentationCustom. Я обновляю свой отчет об ошибке и напишу здесь, если получу ответ от Apple об этом.
bcherry

24

Отсутствие настройки modalPresentationStyleUIModalPresentationCustom решило проблему для меня.

Другими словами, оставив значение по умолчанию для UIModalPresentationFullScreen вместо указания UIModalPresentationCustom, мы устранили проблему исчезновения представления. Обратите внимание, что протокол UIViewControllerTransitioningDelegate по-прежнему соблюдается, даже если оставить это значение по умолчанию. Если я правильно помню, когда-то требовался UIModalPresentationCustom.

Пока работает, пробовал только для неинтерактивных анимаций.


1
Вот это да. Вот и все! Я тестировал без modalPresentationStyle в iOS7 и 8, и он работает в обоих. Спасибо!!
А Рюн Мун

1
Спасибо! Это в сочетании с использованием viewForKey:вместо .viewна viewControllerForKey:исправлениях все вопросы для меня.
bcherry

1
Это устранило проблему для меня без использования viewForKey, но я полагаю, что его тоже следует использовать.
Кевин Слих

5
Хотя это, кажется, решает проблему, важно отметить, что экран за вашим контроллером представления станет черным после его отображения. Это важно, если ваш контроллер представления не является полноэкранным.
Чувак

16

Я нашел этот чрезвычайно полезный ответ в связанной ветке Лефтериса: qaru.site/questions/435 / ... / 27165723/3709173

Подвести итог:

  1. установите для modalPresentationStyle значение .Custom
  2. подкласс UIPresentationController, переопределить shouldRemovePresentersView (с NO)
  3. переопределить PresentationControllerForPresentViewController в вашем классе TransitionDelegate и вернуть свой пользовательский UIPresentationController

+1 в вашем настраиваемом переходе, не добавляйте toView, когда происходит анимация увольнения.

Продемонстрировано здесь:

https://www.dropbox.com/s/7rpkyamv9k9j18v/CustomModalTransition.zip?dl=0 без всяких взломов! это похоже на волшебство! :)


1
Это действительно правильный ответ. Без фокусов, как в принятом. Спасибо, Марк!
Андрей Малыгин

К сожалению, это не работает в iOS 12.4, Xcode 10.3. Экран становится черным после перехода Завершает (все виды были удалены из иерархии Однако, установив свойство «modalPresentationStyle» к «.fullscreen» ДЕЛАЕТ работу Приветствие...
Уомбл

Я пробовал версию Obj-C от Марка и реализацию Swift от gwinyai в своем проекте. К сожалению, ни один из них не работает должным образом. Я использую Xcode 11.1, а цель сборки - iOS 13.0, я пробовал как на устройстве, так и на симуляторе. В моем случае моя основная настройка - это представление коллекции, и когда вы коснетесь одной ячейки, она перейдет к подробному представлению с анимацией. Однако, если я использую анимацию перехода по умолчанию, она работает нормально. Представляющий VC не исчезнет, ​​когда я вернусь к просмотру деталей.
infinity_coding7

8

В iOS 8 вам нужно создать UIPresentationController и реализовать метод, указанный ниже, в UIViewControllerTransitioningDelegate.

- (UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(UIViewController *)presenting sourceViewController:(UIViewController *)source;

Запрашивает у вашего делегата пользовательский контроллер представления, который будет использоваться для управления иерархией представлений при представлении контроллера представления.

Возвращаемое значение:

Контроллер пользовательского представления для управления модальным представлением.

Обсуждение:

Когда вы представляете контроллер представления с использованием стиля представления UIModalPresentationCustom, система вызывает этот метод и запрашивает контроллер представления, который управляет вашим пользовательским стилем. Если вы реализуете этот метод, используйте его для создания и возврата настраиваемого объекта контроллера презентации, который вы хотите использовать для управления процессом презентации.

Если вы не реализуете этот метод или если ваша реализация этого метода возвращает nil, система использует объект контроллера представления по умолчанию. Контроллер представления по умолчанию не добавляет никаких представлений или содержимого в иерархию представлений.

Доступность Доступно в iOS 8.0 и новее.

Для получения дополнительной информации посмотрите видео WWDC 2014:

https://developer.apple.com/videos/wwdc/2014/?include=228

Также имеется образец кода из WWDC под названием «LookInside: адаптивность контроллеров презентации и настраиваемые объекты аниматора», который вы можете загрузить с образца кодовой страницы WWDC 2014.

Возможно, вам придется немного изменить пример кода. Метод инициализации UIPresentationController изменен на:

initWithPresentedViewController:presented presentingViewController:presenting

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


Извините за то, что не просматриваете связанное видео, но я не думаю, что вам нужен пользовательский UIPresentationController, если вы не хотите нестандартную презентацию после завершения анимации, например, круговое представленное представление. Если вам просто нужна другая анимация, реализации UIViewControllerAnimatedTransitioning должно быть достаточно, исходя из моих ограниченных знаний.
Vaddadi Kartick 01

7

вместо [inView insertSubview: toViewController.view вышеSubview: fromViewController.view]; просто добавьте: [inView addSubview: toViewController.view];

if (self.presenting) {

    [transitionContext.containerView addSubview:toViewController.view];
    // your code

} else {
    // your code
}

Вы можете увидеть пример здесь: ссылка, и она работает на iOS 7 и iOS 8


Это должен быть принятый ответ для создания анимации типа UIModalPresentationStyleCustom, поскольку нет необходимости добавлять fromViewController в containerView. Вам нужно только добавить toViewController во время презентации анимации.
Скотт Кайзер

Это очень полезно, на самом деле,
Дмитрий Бондарев

7

Вот исправление Эша для Objective C.

// my attempt at obj-c version of Ash's fix
UIView *theToView = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey].view;
[[[UIApplication sharedApplication] keyWindow] addSubview:theToView];
[transitionContext completeTransition:YES]

Мне пришлось поменять местами порядок и вызвать метод [transitionContext completeTransition:] после добавления представления обратно, чтобы представить новый контроллер представления из блока завершения увольнения другого контроллера представления для правильной работы.

Я не знаю, что это исправит для всех, но в моем приложении это работает. Ура!


5

Я обнаружил, что это отлично работает для Obj-C:

    [transitionContext completeTransition:YES];
    if(![[UIApplication sharedApplication].keyWindow.subviews containsObject:toViewController.view]) {
        [[UIApplication sharedApplication].keyWindow addSubview:toViewController.view];
    }

Вроде нормально работает как на ios7, так и на ios8.


5

я нашел это viewForKey:UITransitionContextToViewKey на ios8 возвращает nil. Так что, если он равен нулю, я беру представление из контроллера представления «to».

Однако это, похоже, приводит к тому, что представление «кому» не перемещается из контейнера в окно при completeTransition:YESвызове. Итак, если viewForKey:UITransitionContextToViewKeyвозвращается ноль, я перехожу кtoVC.view и отслеживаю, что он вернул nil, а после завершения я перемещаю его в начальный супервизор контейнера (который оказывается окном).

Таким образом, этот код работает как на iOS7, так и на iOS8, и должен работать и на iOS9, даже если они исправят это или нет.

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {
    // Get the 'from' and 'to' views/controllers.
    UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    BOOL hasViewForKey = [transitionContext respondsToSelector:@selector(viewForKey:)]; // viewForKey is iOS8+.
    UIView *fromView = hasViewForKey ?
        [transitionContext viewForKey:UITransitionContextFromViewKey] :
        fromVC.view;
    UIView *toView = hasViewForKey ?
        [transitionContext viewForKey:UITransitionContextToViewKey] :
        toVC.view;

    // iOS8 has a bug where viewForKey:to is nil: http://stackoverflow.com/a/24589312/59198
    // The workaround is: A) get the 'toView' from 'toVC'; B) manually add the 'toView' to the container's
    // superview (eg the root window) after the completeTransition call.
    BOOL toViewNilBug = !toView;
    if (!toView) { // Workaround by getting it from the view.
        toView = toVC.view;
    }
    UIView *container = [transitionContext containerView];
    UIView *containerSuper = container.superview; // Used for the iOS8 bug workaround.

    // Perform the transition.
    toView.frame = container.bounds;
    [container insertSubview:toView belowSubview:fromView];
    [UIView animateWithDuration:kDuration delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
        fromView.frame = CGRectOffset(container.bounds, 0, CGRectGetHeight(container.bounds));
    } completion:^(BOOL finished) {
        [transitionContext completeTransition:YES];

        if (toViewNilBug) {
            [containerSuper addSubview:toView];
        }
    }];
}

3

Я обнаружил, что эта ошибка (и многие другие!) Исчезают, если вы установите ее modalPresentationStyle = UIModalPresentationFullScreen. Вы, конечно, по-прежнему получаете собственную анимацию перехода.


2

Я тоже застрял в этом вопросе. Я хотел создать пользовательский переход с полупрозрачным фоном, где я все еще мог видеть контроллер представления, из которого я пришел, но у меня был только черный фон. Я обнаружил, что ответ Марка Арона в этой теме помог мне, но он написан на Objective C, поэтому вот версия этого ответа для Swift 3, которую я тестировал для iOS 9 и iOS 10:

  1. Создайте подкласс UIPresentationController. Замените shouldRemovePresentersView на false следующим образом:

    class ModalPresentationController: UIPresentationController {
    
    override var shouldRemovePresentersView: Bool {
    return false
    }
    
    override func containerViewWillLayoutSubviews() {
    presentedView?.frame = frameOfPresentedViewInContainerView
    }
    }
  2. В том месте, где вы создаете экземпляр нового контроллера представления и устанавливаете его делегат перехода, укажите, что вы хотите, чтобы он отображал настраиваемый стиль модального представления следующим образом:

    let newVC = mainStoryboard.instantiateViewController(withIdentifier: "newVC") as! NewViewController 
    
    newVC.transitioningDelegate = self
    
    newVC.modalPresentationStyle = UIModalPresentationStyle.custom
    
    newVC.modalPresentationCapturesStatusBarAppearance = true //optional
    
    present(newVC, animated: true, completion: nil)
  3. Теперь переопределите метод presentationController вашего UIViewControllerTransitioningDelegate и верните свой пользовательский UIPresentationController. У меня был мой как расширение моего текущего класса:

    extension CurrentViewController: UIViewControllerTransitioningDelegate {
    
    //this is where you implement animationController(forPresented) and animationController(forDismissed) methods
    
    func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
    
    return ModalPresentationController(presentedViewController: presented, presenting: source)
    
    }
    }

Еще одно замечание: вам не следует пытаться ссылаться на свой fromView в своем классе presentAnimator. Это будет ноль, и вы получите ошибку во время выполнения. Кроме того, если вы реализуете такие вещи, вы получите свой собственный переход с его анимацией и полупрозрачным фоном, если вы его сделаете.


Этот iis - отличный пример создания пользовательской модальной презентации в Swift 3! Спасибо @gwinyai! Я очень зациклился на этом, пока не нашел пример, показывающий новый API Swift 3, presentationController(forPresented presented UIViewController,... потому что предыдущий API Swift не расстроил компилятора, но не был вызван.
Наталья

2

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

В некоторых ответах упоминается изменение modalPresentationStyleна .overFullScreen. Это правильно, .overCurrentContextтоже подойдет. Это ожидаемо, и поведение Apple задокументировано. Но почему это работает не для всех? К чему весь хакерский код и комбинации этого с чем-то еще, и сумасшедшие вещи, которых вам не следует делать?

Оказывается, вам нужно установить стиль представления ДО ЗАГРУЗКИ ВИДА . Не после. Сделайте это в init, или сделайте это из предыдущего контроллера, или как хотите - до тех пор, пока не загрузится представление.


1
Я установил стиль презентации .overCurrentContext до загрузки представления (в initконтроллере представления), и проблема все еще возникает
ricardopereira

1

Использование нового UIModalPresentationOverCurrentContext исправило это для меня. Мой первоначальный переход на iOS 7 заключался в том, чтобы иметь размытый фон представления под модальным окном.


По какой-то причине это не позволяет взаимодействовать с представлением внизу, где UIModalPresentationCurrentContext делал в iOS 7 .. Есть мысли?
Кристофер Вирт,

Хм для меня на iOS 10 .overCurrentContext приводит к этой ошибке, а .fullscreen - нет. Я пришла сюда в надежде найти исправление для использования .overCurrentContext, но пока ничего не похоже, что это будет работать в iOS 10, кроме, возможно, подкласса UIPresentationController ...
Наталья

0

Хорошо, ребята, я думаю, что решил один случай, когда «рабочий аниматор» перестает работать должным образом, когда вы создаете приложение в iOS 13 и выше.

Env Xcode 11.1, iOS 13.1

Проблема

То, что я хочу сделать, очень просто: у меня есть представление коллекции, при нажатии на ячейку происходит переход к подробному представлению. Вместо того, чтобы использовать утомительный стиль по умолчанию «представить модально», я хочу сделать его более интересным, поэтому я написал аниматор для перехода контроллера представления.

Я установил переход в IB путем перетаскивания из моей коллекции VC в подробный VC. Стиль перехода - «Представлять модально», а для презентации установлен «Полноэкранный режим».

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

1. Сразу после вызова следующей строки из функции 'animateTransition ()' просмотр коллекции возобновляется и отображается

transitionContext.completeTransition(true)

2. до тех пор, пока подробное представление не полностью покрывает представление коллекции, представление коллекции не исчезнет при переходе обратно от представления подробностей.

Решение

Если честно, я мало знаю о том, как работает анимированный переход. Так что я могу следить только за этим и другим постом , пробуя каждый из ответов. К сожалению, у меня ни один из них не работает. Наконец, я дошел до того, что единственное, что я могу настроить, - это стиль представления segue в IB (что я должен был сделать в самом начале). Когда я устанавливаю презентацию на «Во весь экран», происходит чудо, и моя проблема решается. Подробное представление может отображаться в полноэкранном режиме с анимацией, и когда оно закрыто, я могу видеть как представление коллекции как фон, так и анимированное подробное представление.

Затем еще одно открытие по дороге

3. Для обращения к toView и fromView работают оба следующих метода.

Косвенно:

transitionContext.viewController(forKey: .to)?.view
transitionContext.viewController(forKey: .from)?.view

Прямо способом:

transitionContext.view(forKey: .to)
transitionContext.view(forKey: .from)

Но когда я переключил стиль перехода на 'Over Full Screen', прямой способ вернуть 'nil' как для 'toView', так и 'fromView' и только косвенно работает, эта проблема также упоминается в другом сообщении , поэтому я думаю, что это стоит разместить здесь свое маленькое открытие.

Надеюсь, это будет полезно кому-то в будущем.


0

У меня была такая же проблема при отключении контроллера представления содержимого.

В моем приложении есть этот родительский контроллер представления, показывающий контроллер дочернего представления (представляющий vc) модально. Затем при нажатии на подпредставление в childVC отображается другой vc (который я называю контроллером представления содержимого (представлен vc))

Моя проблема в том, что при отклонении contentVC (теперь представляющий vc) он должен перейти в дочерний VC (теперь представленный VC), но как только мой пользовательский переход завершается, childVC внезапно исчезает, показывая родительский VC.

Что я сделал для решения этой проблемы, так это

  1. измените значение .modalPresentationStylechildVC, представленное parentVC, со значения .automaticпо умолчанию на.fullscreen .
  2. Затем изменил и .modalPresentationStylecontentVC на .fullscreen.

Это решает проблему. но он не будет показывать ваш дочерний VC как таблицу стилей карты поверх parentVC (при использовании.overCurrentContext или автоматически), который является новым в iOS 13.

Хотелось бы знать, есть ли какое-либо решение, которое сохранит таблицу стилей карты для childVC при представлении родителем.


-3

добавляет контроллер представления как дочерний элемент другого контроллера представления.

[self addChildViewController:childViewController];                 

проверьте и дайте мне знать.


я не понимаю, вы можете описать это с помощью кодирования?
NiravPatel

проверьте эту документацию Apple developer.apple.com/library/ios/featuredarticles/…
Rushabh

это никоим образом не отвечает на вопрос. ChildViewControllers не участвуют ни в какой части пользовательских переходов, это совершенно другая тема.
Andras M.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.