У меня возникла одна проблема, и я описал ее ниже.
Я использую 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];
вызове первый контроллер представления внезапно исчезает, а под контроллером второго представления отображается черный экран.
Есть ли у кого-нибудь идеи? Спасибо.
источник
modalPresentationStyle = UIModalPresentationFullScreen
. Вы, конечно, по-прежнему получаете собственную анимацию перехода.Я считаю, что следует лучше объяснить причину этого.
Представление исчезает, потому что вы извлекаете представление контроллера представления представления из его исходного местоположения (иерархии представлений), помещаете его в containerView, который предоставляет ваш аниматор, но никогда не возвращает его обратно после завершения анимации. Таким образом, представление контроллера представления полностью удалено с его супервизором (containerView) из окна.
В iOS 7 система всегда возвращала представления контроллеров представлений, которые участвуют в презентации (представляются и представляются), на их исходные места после того, как переход завершает анимацию автоматически. Этого больше не происходит с некоторыми стилями представления в iOS 8.
Правило очень простое: аниматор должен манипулировать представлением контроллера представления только в том случае, если представление этого контроллера представления будет полностью скрыто (удалено из иерархии представлений) к концу перехода . Другими словами, это означает, что после завершения начальной анимации презентации будет видно только представление представленного контроллера представления, а не представление контроллера представления представления. Например, если вы установите непрозрачность представления представленного контроллера представления на 50% и используете UIModalPresentationFullScreen, вы не сможете увидеть представление представления контроллера представления под представленным, но если вы используете UIModalPresentationOverFullscreen - вы будете (UIPresentationController's
shouldRemovePresentersView
за указание этого отвечает метод ).Почему бы не разрешить аниматору постоянно манипулировать представлением контроллера представления? Прежде всего, если представление контроллера представления будет оставаться видимым после завершения анимации в течение всего жизненного цикла презентации, нет необходимости вообще его анимировать - оно просто остается на месте. Во-вторых, если право собственности на этот контроллер представления передается контроллеру представления, контроллер представления, скорее всего, не будет знать, как разместить представление этого контроллера представления, когда это необходимо, например, при изменении ориентации, но первоначальный владелец представляющего контроллера представления делает .
В iOS 8
viewForKey:
был введен метод получения представлений, которыми манипулирует аниматор. Во-первых, это помогает следовать описанному выше правилу, возвращая nil всякий раз, когда аниматор не должен касаться вида. Во-вторых, аниматор может возвращать другой вид для анимации. Представьте, что вы реализуете презентацию, похожую на лист формы. В этом случае вам нужно добавить тень или украшение вокруг представленного представления контроллера представления. Аниматор вместо этого анимирует это украшение, и представленное представление контроллера представления будет дочерним для этого украшения.viewControllerForKey:
не исчезает, его все еще можно использовать, если требуется прямой доступ к контроллерам представлений, но аниматор не должен делать никаких предположений относительно представлений, которые ему нужно анимировать.Есть несколько вещей, которые вы можете сделать, чтобы правильно исправить проблему с исчезающим представлением представления контроллера представления, когда вы явно помещаете его в представление контейнера аниматора:
Если не нужно анимировать представление контроллера представления представления, используйте,
viewForKey:
чтобы получить представления для анимации вместо того, чтобы обращаться к представлениям контроллера напрямую.viewForKey:
может возвращать ноль или даже совершенно разные представления.Если вы хотите анимировать представление контроллеров представления представления, вам следует рассмотреть возможность использования
UIModalPresentationFullScreen
стиля или продолжить использованиеUIModalPresentationCustom
и реализовать свой собственный подкласс UIPresentationController сshouldRemovePresentersView
возвратомYES
. На самом деле, реализация этого метода является то, основное различием между внутренними контроллерами представления , определенныхUIModalPresentationFullScreen
иUIModalPresentationCustom
стилями , кроме того факта , что последние позволяют использовать контроллеры пользовательских представлений.Во всех других редких случаях вам придется вернуть представление контроллера представления в исходное местоположение, как предлагали другие ответы.
источник
viewControllerForKey:
«ыview
s только когдаviewForKey:
возвращается NIL, и я все еще должен был повторно добавить его в окно вручную. У вас есть пример кода, работающего без этого обходного пути?viewForKey:
возвращается nil, тогда вам наверняка придется повторно добавить представление контроллера представления представления в окно, если вы удалите его из него в своем аниматоре. В случае, если viewForKey возвращает фактическое представление контроллера представления, можно безопасно переместить это представление, поскольку UIKit вернет его в исходное положение после завершения жизненного цикла презентации.В iOS 8 вы должны манипулировать представлениями, возвращаемыми,
viewForKey:
вместо.view
свойств контроллеров представлений, возвращаемыхviewControllerForKey:
. Это не особо ясно из документации по бета-версии, но если вы посмотрите исходный код UIViewControllerTransitioning.h, вы увидите этот комментарий вышеviewControllerForKey:
:Поэтому вместо настройки кадров и т. Д.
toViewController.view
Используйте возвращаемое значение[transitionContext viewForKey:UITransitionContextToViewKey]
.Если ваше приложение должно поддерживать iOS7 и / или Xcode 5, вы можете использовать простой метод категорий в UIViewController, например:
Затем получите
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.источник
manipulating
взгляды венчурных капиталистов или нет ...viewForKey
ошибку в GM. Другие тоже? Вы нашли разумное решение?- viewForKey
// viewForKey: может вернуть nil, что указывало бы на то, что аниматор не должен манипулировать представлением связанного контроллера представления. Возвратnil
не является ошибкой.viewForKey
возвращает из представления и для просмотра. Так что, возможно, он намеренно возвращает nil для UIModalPresentationCustom. Я обновляю свой отчет об ошибке и напишу здесь, если получу ответ от Apple об этом.Отсутствие настройки
modalPresentationStyle
UIModalPresentationCustom решило проблему для меня.Другими словами, оставив значение по умолчанию для UIModalPresentationFullScreen вместо указания UIModalPresentationCustom, мы устранили проблему исчезновения представления. Обратите внимание, что протокол UIViewControllerTransitioningDelegate по-прежнему соблюдается, даже если оставить это значение по умолчанию. Если я правильно помню, когда-то требовался UIModalPresentationCustom.
Пока работает, пробовал только для неинтерактивных анимаций.
источник
viewForKey:
вместо.view
наviewControllerForKey:
исправлениях все вопросы для меня.Я нашел этот чрезвычайно полезный ответ в связанной ветке Лефтериса: qaru.site/questions/435 / ... / 27165723/3709173
Подвести итог:
+1 в вашем настраиваемом переходе, не добавляйте toView, когда происходит анимация увольнения.
Продемонстрировано здесь:
https://www.dropbox.com/s/7rpkyamv9k9j18v/CustomModalTransition.zip?dl=0 без всяких взломов! это похоже на волшебство! :)
источник
В iOS 8 вам нужно создать UIPresentationController и реализовать метод, указанный ниже, в UIViewControllerTransitioningDelegate.
Для получения дополнительной информации посмотрите видео WWDC 2014:
https://developer.apple.com/videos/wwdc/2014/?include=228
Также имеется образец кода из WWDC под названием «LookInside: адаптивность контроллеров презентации и настраиваемые объекты аниматора», который вы можете загрузить с образца кодовой страницы WWDC 2014.
Возможно, вам придется немного изменить пример кода. Метод инициализации UIPresentationController изменен на:
Раньше его представляли, а потом презентовали. Просто поменяйте их местами, и все должно работать.
источник
вместо [inView insertSubview: toViewController.view вышеSubview: fromViewController.view]; просто добавьте: [inView addSubview: toViewController.view];
Вы можете увидеть пример здесь: ссылка, и она работает на iOS 7 и iOS 8
источник
Вот исправление Эша для Objective C.
Мне пришлось поменять местами порядок и вызвать метод [transitionContext completeTransition:] после добавления представления обратно, чтобы представить новый контроллер представления из блока завершения увольнения другого контроллера представления для правильной работы.
Я не знаю, что это исправит для всех, но в моем приложении это работает. Ура!
источник
Я обнаружил, что это отлично работает для Obj-C:
Вроде нормально работает как на ios7, так и на ios8.
источник
я нашел это
viewForKey:UITransitionContextToViewKey
на ios8 возвращает nil. Так что, если он равен нулю, я беру представление из контроллера представления «to».Однако это, похоже, приводит к тому, что представление «кому» не перемещается из контейнера в окно при
completeTransition:YES
вызове. Итак, еслиviewForKey:UITransitionContextToViewKey
возвращается ноль, я перехожу кtoVC.view
и отслеживаю, что он вернул nil, а после завершения я перемещаю его в начальный супервизор контейнера (который оказывается окном).Таким образом, этот код работает как на iOS7, так и на iOS8, и должен работать и на iOS9, даже если они исправят это или нет.
источник
Я обнаружил, что эта ошибка (и многие другие!) Исчезают, если вы установите ее
modalPresentationStyle = UIModalPresentationFullScreen
. Вы, конечно, по-прежнему получаете собственную анимацию перехода.источник
Я тоже застрял в этом вопросе. Я хотел создать пользовательский переход с полупрозрачным фоном, где я все еще мог видеть контроллер представления, из которого я пришел, но у меня был только черный фон. Я обнаружил, что ответ Марка Арона в этой теме помог мне, но он написан на Objective C, поэтому вот версия этого ответа для Swift 3, которую я тестировал для iOS 9 и iOS 10:
Создайте подкласс UIPresentationController. Замените shouldRemovePresentersView на false следующим образом:
В том месте, где вы создаете экземпляр нового контроллера представления и устанавливаете его делегат перехода, укажите, что вы хотите, чтобы он отображал настраиваемый стиль модального представления следующим образом:
Теперь переопределите метод presentationController вашего UIViewControllerTransitioningDelegate и верните свой пользовательский UIPresentationController. У меня был мой как расширение моего текущего класса:
Еще одно замечание: вам не следует пытаться ссылаться на свой fromView в своем классе presentAnimator. Это будет ноль, и вы получите ошибку во время выполнения. Кроме того, если вы реализуете такие вещи, вы получите свой собственный переход с его анимацией и полупрозрачным фоном, если вы его сделаете.
источник
presentationController(forPresented presented UIViewController,...
потому что предыдущий API Swift не расстроил компилятора, но не был вызван.Столкнувшись с этой проблемой, я был очень сбит с толку, потому что не так давно написал что-то почти идентичное, что работало нормально. Пришел сюда в поисках ответов, чтобы найти исправления, которые выглядят довольно хакерскими и, похоже, не понимают основную причину ... на самом деле это очень легко исправить.
В некоторых ответах упоминается изменение
modalPresentationStyle
на.overFullScreen
. Это правильно,.overCurrentContext
тоже подойдет. Это ожидаемо, и поведение Apple задокументировано. Но почему это работает не для всех? К чему весь хакерский код и комбинации этого с чем-то еще, и сумасшедшие вещи, которых вам не следует делать?Оказывается, вам нужно установить стиль представления ДО ЗАГРУЗКИ ВИДА . Не после. Сделайте это в init, или сделайте это из предыдущего контроллера, или как хотите - до тех пор, пока не загрузится представление.
источник
.overCurrentContext
до загрузки представления (вinit
контроллере представления), и проблема все еще возникаетИспользование нового UIModalPresentationOverCurrentContext исправило это для меня. Мой первоначальный переход на iOS 7 заключался в том, чтобы иметь размытый фон представления под модальным окном.
источник
Хорошо, ребята, я думаю, что решил один случай, когда «рабочий аниматор» перестает работать должным образом, когда вы создаете приложение в iOS 13 и выше.
Env Xcode 11.1, iOS 13.1
Проблема
То, что я хочу сделать, очень просто: у меня есть представление коллекции, при нажатии на ячейку происходит переход к подробному представлению. Вместо того, чтобы использовать утомительный стиль по умолчанию «представить модально», я хочу сделать его более интересным, поэтому я написал аниматор для перехода контроллера представления.
Я установил переход в IB путем перетаскивания из моей коллекции VC в подробный VC. Стиль перехода - «Представлять модально», а для презентации установлен «Полноэкранный режим».
Когда он показывает подробный вид, все работает, как ожидалось. Однако, когда я закрываю подробное представление и возвращаюсь к представлению коллекции, я вижу только анимированное представление подробностей, представление коллекции просто исчезает. Я ковырял тут и там и у меня есть несколько открытий
1. Сразу после вызова следующей строки из функции 'animateTransition ()' просмотр коллекции возобновляется и отображается
2. до тех пор, пока подробное представление не полностью покрывает представление коллекции, представление коллекции не исчезнет при переходе обратно от представления подробностей.
Решение
Если честно, я мало знаю о том, как работает анимированный переход. Так что я могу следить только за этим и другим постом , пробуя каждый из ответов. К сожалению, у меня ни один из них не работает. Наконец, я дошел до того, что единственное, что я могу настроить, - это стиль представления segue в IB (что я должен был сделать в самом начале). Когда я устанавливаю презентацию на «Во весь экран», происходит чудо, и моя проблема решается. Подробное представление может отображаться в полноэкранном режиме с анимацией, и когда оно закрыто, я могу видеть как представление коллекции как фон, так и анимированное подробное представление.
Затем еще одно открытие по дороге
3. Для обращения к toView и fromView работают оба следующих метода.
Косвенно:
Прямо способом:
Но когда я переключил стиль перехода на 'Over Full Screen', прямой способ вернуть 'nil' как для 'toView', так и 'fromView' и только косвенно работает, эта проблема также упоминается в другом сообщении , поэтому я думаю, что это стоит разместить здесь свое маленькое открытие.
Надеюсь, это будет полезно кому-то в будущем.
источник
У меня была такая же проблема при отключении контроллера представления содержимого.
В моем приложении есть этот родительский контроллер представления, показывающий контроллер дочернего представления (представляющий vc) модально. Затем при нажатии на подпредставление в childVC отображается другой vc (который я называю контроллером представления содержимого (представлен vc))
Моя проблема в том, что при отклонении contentVC (теперь представляющий vc) он должен перейти в дочерний VC (теперь представленный VC), но как только мой пользовательский переход завершается, childVC внезапно исчезает, показывая родительский VC.
Что я сделал для решения этой проблемы, так это
.modalPresentationStyle
childVC, представленное parentVC, со значения.automatic
по умолчанию на.fullscreen
..modalPresentationStyle
contentVC на.fullscreen
.Это решает проблему. но он не будет показывать ваш дочерний VC как таблицу стилей карты поверх parentVC (при использовании
.overCurrentContext
или автоматически), который является новым в iOS 13.Хотелось бы знать, есть ли какое-либо решение, которое сохранит таблицу стилей карты для childVC при представлении родителем.
источник
добавляет контроллер представления как дочерний элемент другого контроллера представления.
проверьте и дайте мне знать.
источник