"З контролера перегляду" зникає за допомогою 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's як перегляд ключового вікна:

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

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


2
Я також бачив це питання. iOS 8 представляє новий метод та ключі для доступу до fromView та toView (Примітка: не переглядає контролер) Схоже, ці посилання не втрачаються під час переходу. Ви можете додати їх до подання контейнера, як зазвичай, якби ви тільки що отримали їх з контролерів перегляду.
tapi

1
Я бачив подібні дивацтва iOS 8, коли намагався додати підпогляди до перегляду мого навігаційного контролера в viewDidLoad. Повторне додавання погляду navigationController до keyWindow, здавалося, зробило трюк, велике спасибі, Еш!
табер

1
Я все ще бачу це в GM (і це виправлення все ще працює). Чи інші бачать те саме? Це лише зміна API?
rjkaplan

21
Я виявив, що ця помилка (та багато іншого!) Зникає, якщо встановити modalPresentationStyle = UIModalPresentationFullScreen. Звичайно, ви все одно отримаєте власну анімацію переходу.
Кріс

1
Дякуємо @AshFurrow Гарний спосіб вирішення, поки він не буде виправлений!
Кандельвія

78

Я відчуваю, що міркування щодо цього слід пояснити краще.

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

У iOS 7 система завжди повертала погляди контролерів перегляду, які беруть участь у презентації (представляють та представляють), на їх початкові місця, після того як перехід автоматично завершиться анімацією. Це більше не відбувається для деяких стилів презентації в iOS 8.

Правило дуже просте: аніматор повинен маніпулювати поданням контролера подання подання лише тоді, коли подання цього контролера подання буде повністю приховано (видалено з ієрархії подання) до кінця переходу . Іншими словами, це означає, що після завершення початкової анімації презентації буде видно лише представлений подання контролера подання, а не подання контролера подання подання. Наприклад, якщо встановити непрозорість подання представленого контролера перегляду 50% і використовувати UIModalPresentationFullScreen, ви не зможете побачити подання виду контролера перегляду під представленим, але якщо ви будете використовувати UIModalPresentationOverFullscreen - ви ( shouldRemovePresentersViewметод UIPresentationController несе відповідальність за уточнення цього).

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

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

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

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

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

  2. Якщо ви хочете анімувати подання контролерів подання представлення даних, вам слід розглянути можливість використання UIModalPresentationFullScreenстилю або продовжити використання UIModalPresentationCustomта реалізацію власного підкласу UIPresentationController з shouldRemovePresentersViewповерненням YES. Фактично, реалізація цього методу є основною відмінністю внутрішніх контролерів презентації, визначених UIModalPresentationFullScreenта UIModalPresentationCustomстилями, крім того, що останній дозволяє використовувати власні контролери презентації.

  3. У всіх інших рідкісних випадках вам доведеться повернути подання контролера подання подання до його початкового місця, як запропоновано інші відповіді.


2
Це дуже дивно, тому що цей код покладається на viewControllerForKey:s views лише тоді, коли viewForKey:повертається нуль, і мені все одно довелося повторно додавати його до вікна вручну. Чи є у вас приклад роботи коду без цього вирішення?
Еш Борозен

Ну, якщо viewForKey:поверне нуль, то точно вам доведеться знову додати подання контролера подання подання до вікна, якщо ви вилучите його з нього в аніматорі. У випадку, якщо viewForKey поверне фактичний вигляд контролера перегляду, можна перенести це уявлення, оскільки UIKit поверне його у вихідне положення після закінчення життєвого циклу презентації.
egdmitry

Дякуємо, що пояснили міркування цього питання. Ви абсолютно праві. Переміщення позиції подання в ієрархії перегляду, не замінюючи його, очевидно, змусить його зникнути (опублікуйте iOS 8, і я зараз працюю з iOS 10!) Дякую за уточнення.
Глина Елліс

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: Завдяки графлі за пропозицію, використання UIModalPresentationFullScreen виправляє проблему. Можливо, це не помилка. Apple може подумати, що UIModalPresentationCustom змінює лише перегляд вхідного модалу. Якщо ви хочете змінити вихідний вигляд, вам потрібно гарантувати повне екранне представлення нового перегляду? У будь-якому випадку, ви повинні використовувати viewForKeyі UIModalPresentationFullScreen.


2
Помилка viewForKey зводила мене з розуму! - дякую за подачу. FWIW мій перехід працює чудово, отримуючи представлення з UITransitionContextToViewControllerKey, але мій перехід застосовує лише трансформацію до всього перегляду. Я не впевнений, чи слід це трактувати як manipulatingпогляди на ВК чи ні ...
MathewS

1
Нічого собі - це горіхи. Я цього не бачив у розбіжності - ймовірно, тому, що це просто невеликий коментар. Дійсно засмучує, коли Apple витягує такий трюк. Пальці схрестилися біля вашого радара.
Еш Бороз

Я бачу viewForKeyпомилку і в ГМ. Є й інші? Ви знайшли для цього розумне рішення?
rjkaplan

2
Я подумав, згідно з коментарем - viewForKey// viewForKey: може повернути нуль, який би вказував на те, що аніматор не повинен маніпулювати поданням пов'язаного контролера перегляду. Повернення nil- це не помилка.
Кен Куан

4
@kenKuan ви можете мати рацію. при використанні UIModalPresentationFullScreen, viewForKeyповертає погляд з точки зору та перегляд. Тож може бути навмисно, що він повертає нуль для UIModalPresentationCustom. Я оновлюю свій звіт про помилку і опублікую тут, якщо почую про це від Apple.
бчеррі

24

Чи не встановлюючи modalPresentationStyleна UIModalPresentationCustom виправили проблему для мене.

Іншими словами, залишаючи за замовчуванням UIModalPresentationFullScreen замість вказівки UIModalPresentationCustom виправлено проблему, що зникає. Зверніть увагу, що протокол UIViewControllerTransitioningDelegate, як видається, досі дотримується, навіть якщо це значення залишається за замовчуванням. Якщо я пам'ятаю правильно, колись час UIModalPresentationCustom був вимогою.

Працює поки що, спробував це лише для неінтерактивної анімації.


1
Ого. Це зробили! Я протестував без modalPresentationStyle в iOS7 & 8, і це працює знайти в обох. Дякую!!
Ah Ryun Moon

1
Дякую! Це в поєднанні з використанням viewForKey:замість того, .viewщоб viewControllerForKey:виправляти всі проблеми для мене.
бчеррі

1
Це вирішило для мене проблему, не використовуючи viewForKey, але я вважаю, що її слід також використовувати.
Кевін Слієч

5
Хоча це, як видається, вирішує проблему, важливо зауважити, що екран, який знаходиться за вашим контролером зору, стане чорним після його відображення. Це важливо, якщо у вашого контролера перегляду немає повного екрана.
Чувак

16

Я знайшов цю надзвичайно корисну відповідь у пов'язаній темі від Lefteris: https://stackoverflow.com/a/27165723/3709173

Підсумовуючи це:

  1. встановіть modalPresentationStyle на .Custom
  2. підклас UIPresentationController, заміняти слідRemovePresentersView (з НІ)
  3. замінити презентаціюControllerForPresentedViewController у класі 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 від впровадження проекту Mark та gwinyai Swift у своєму проекті. На жаль, жоден з них не працює так, як очікувалося. Я використовую 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, система викликає цей метод і запитує контролер презентації, який керує вашим користувацьким стилем. Якщо ви реалізуєте цей метод, використовуйте його для створення та повернення спеціального об'єкта контролера презентації, який ви хочете використовувати для управління процесом презентації.

Якщо ви не реалізуєте цей метод, або якщо ваша реалізація цього методу повертає нуль, система використовує об'єкт контролера презентації за замовчуванням. Контролер презентації за замовчуванням не додає в ієрархію перегляду жодних переглядів чи вмісту.

Доступність Доступно в iOS 8.0 та новіших версіях.

Для отримання додаткової інформації дивіться відео WWDC 2014:

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

Також є зразок коду з WWDC під назвою "LookInside: Адаптивність контролерів презентації та спеціальні об'єкти аніматора", який ви можете завантажити з кодової сторінки WWDC 2014.

Можливо, вам доведеться трохи змінити зразок коду. Метод init UIPresentationController змінено на:

initWithPresentedViewController:presented presentingViewController:presenting

Перед тим, як презентувати, а потім представити. Просто поміняйте їх, і це повинно працювати.


Вибачте за те, що ви не переглядали пов’язане відео, але я не думаю, що вам потрібен користувальницький UIPresentationController, якщо ви не хочете нестандартної презентації після завершення анімації, як круговий поданий вид. Якщо ви просто хочете іншої анімації, впровадження UIViewControllerAnimatedTransitioning повинно бути достатньо, виходячи з моїх обмежених знань.
Ваддаді Картік

7

замість [inView insertSubview: toViewController.view aboveSubview: 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 до контейнерного перегляду. Вам потрібно лише додати toViewController під час представлення анімації.
Скотт Кайзер

Це дуже корисно, насправді
Дмитро Бондарев

7

Ось об'єктивна версія 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]

Мені довелося поміняти порядок і викликати метод [переходуКонтекст завершеного переходу:] після додавання перегляду назад, щоб отримати представлений новий контролер подання з блоку завершення звільнення іншого контролера перегляду, щоб він працював правильно.

Я не знаю, що це буде виправлено для всіх, але це працює в моєму додатку. Ура!


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. Тож якщо це нульове значення, я перехоплюю подання від контролера перегляду "до".

Однак, схоже, це призводить до того, що подання "до" не переміщується з контейнера у вікно, коли completeTransition:YESвикликається. Тож якщо viewForKey:UITransitionContextToViewKeyповернеться нульовим, я перепадаю наtoVC.view і відслідковую той факт, що він повернув нуль, і після завершення переміщую його до початкового огляду контейнера (що трапляється у вікно).

Таким чином, цей код працює як на 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. Тепер замініть метод presenController вашого 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)
    
    }
    }

Ще одне, що слід зауважити, - ви не повинні намагатися посилатись на ваш viewView у вашому класі presentAnimator. Це буде нульовим, і ви отримаєте помилку під час виконання. Крім цього, якщо ви реалізуєте такі речі, як ви отримаєте власний перехід із його анімацією та напівпрозорим фоном, якщо ви зробите такий.


Цей iis - чудовий приклад для здійснення спеціальної модальної презентації у Swift 3! Дякую @gwinyai! Я дуже зациклювався на цьому, поки не знайшов приклад, який показав новий API швидкого 3, presentationController(forPresented presented UIViewController,... оскільки попередній API інтерфейсу не засмутив компанію, але не викликав.
Наталія

2

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

У деяких відповідях згадується зміна modalPresentationStyleна .overFullScreen. Це правильно, .overCurrentContextтеж би працювало. Цього, як очікується, і поведінка Apple документи. Але чому це не працює для всіх? Чому весь хакі-код і поєднання цього з чимось іншим, і шалені речі, якими ви не повинні займатися?

Виявляється, вам потрібно встановити стиль презентації ДО ПЕРЕГЛЯДУВАННЯ ЗАВДАННЯ . Не після. Зробіть це в init або зробіть це з попереднього контролера, або як би ви хотіли - доти, доки він не завантажується.


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

1

Використання нового UIModalPresentationOverCurrentContext виправило його для мене. Мій оригінальний перехід на iOS 7 полягав у тому, щоб під модалом було розмито фон подання.


Чомусь це, здається, не дозволяє взаємодія з представленням під ним, де UIModalPresentationCurrentContext робив в iOS 7 .. Будь-які думки?
Крістофер Вірт

Хм для мене на iOS 10, .overCurrentContext призводить до цієї помилки, але. Fullllscreen цього не робить. Я приїхав сюди, сподіваючись на виправлення для використання .overCurrentContext, але поки що нічого не здається, що він буде працювати в iOS 10, за винятком, можливо, підкласифікації UIPresentationController ...
Наталія

0

Гаразд, хлопці, я думаю, що я вирішу один випадок, коли "працюючий аніматор" перестає працювати належним чином, коли ви створюєте додаток в iOS 13 і вище.

Env Xcode 11.1, iOS 13.1

Проблема

Те, що я хочу зробити, дуже просте: у мене перегляд колекції, коли натискається на комірку, вона перейде в детальний вигляд. Замість того, щоб використовувати нудний за замовчуванням стиль «присутній модально», я хочу зробити його цікавішим, тому я написав аніматора для переходу контролера перегляду.

Я встановив segue в IB, перетягуючи з моєї колекції VC до деталей VC. Стиль segue - "Present modally", а презентація встановлена ​​на "Full Screen".

Коли він показує детальний вид, все працює як очікувалося. Однак, коли я відхиляю детальний вигляд і повертаюсь до перегляду колекції, я можу бачити лише перегляд анімованих деталей, перегляд колекції просто минув. Я ткнув туди-сюди, і у мене є кілька відкриттів

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)

Але коли я переключив стиль segue на "Over Full Screen", безпосередньо повернути "nil" для "toView" і "fromView", і лише побічно це працює, ця проблема також згадується в іншому дописі , тому я думаю, що це варто щоб опублікувати моє маленьке відкриття тут.

Сподіваюся, що це буде корисно комусь у майбутньому.


0

У мене була така ж проблема, коли відхиляли контролер перегляду вмісту.

У моєму додатку є цей контролер батьківського перегляду, який відображає контролер дочірнього перегляду (представляючи vc) в режимі мода. Потім при натисканні на підвід у дочірньому вікні відображається інший vc (який я викликаю контролером перегляду вмісту (представлений vc))

Моя проблема полягає в тому, що при відхиленні contentVC (теперішній випускний ПК) він повинен перейти до дочірнього VC (зараз представлений VC), але як тільки мій користувацький перехід закінчиться, childVC раптово зникає, показуючи батьківський VC.

Що я зробив для вирішення цього питання

  1. змінити .modalPresentationStyleдочірню програму VC, представлену parentVC, з за замовчуванням .automaticна .fullscreen.
  2. Потім змінив .modalPresentationStyleвміст contentVC .fullscreenтакож.

Це вирішує питання. але він не відображатиме вашій дитині VC у вигляді аркуша картки зверху nadVVVER (під час використання .overCurrentContextабо автоматичного), що є новим у iOS 13.

Хочеться дізнатися, чи є якесь рішення, яке збереже аркуш картки для childVC, коли він буде представлений батьком.


-3

додає контролер подання як дочірку іншого контролера перегляду.

[self addChildViewController:childViewController];                 

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


я не отримую, чи можете ви описати це за допомогою кодування?
NiravPatel

перевірити цю документацію на розробник
яблук.apple.com/library/ios/featuredarticles/…

це жодним чином не відповідає на питання. ChildViewControllers не причетні до жодної частини користувацьких переходів, вони є абсолютно різною темою.
Андрас М.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.