Пользовательский переход UIViewController застрял на iOS13

Я реализовал настраиваемый переход между двумя контроллерами представления в моем приложении для iOS, и он отлично работал с iOS 10, 11 и 12.

Теперь я хочу подготовить его для iOS 13, используя Xcode 11 beta 6 и iOS 13 beta 8, но переход застрял.

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

Я обнаружил, что в методе animatePresentation(context: UIViewControllerContextTransitioning) в context не возвращает представление "из", поэтому context.view(forKey: .from) возвращается nil.

Что я должен делать без обзора?

FlyUpTransition.swift

class FlyUpTransition: NSObject, UIViewControllerAnimatedTransitioning {

    var mode: Mode = .present

    enum Mode {
        case present
        case dismiss
    }

    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return TimeInterval(0.45)
    }

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        switch mode {
        case .present:
            animatePresentation(context: transitionContext)
        case .dismiss:
            animateDismissal(context: transitionContext)
        }
    }

    func animatePresentation(context: UIViewControllerContextTransitioning) {
        guard let fromView = context.view(forKey: .from), let toView = context.view(forKey: .to) else { return }
        ...
    }

    func animateDismissal(context: UIViewControllerContextTransitioning) {
        guard let fromView = context.view(forKey: .from), let toView = context.view(forKey: .to) else { return }
        ...
    }
}

4 ответа

Решение

Хорошо, это было легко, хотя это ломающее изменение API Apple.

viewController.modalPresentationStyle = .fullScreen

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

TL;DR

Это ошибка iOS, но вы можете использовать context.viewController(forKey:.from).view как обходной путь.

Полная информация

Похоже, это ошибка в iOS 13.0. Что касается iOS 13.1 beta 3, она все еще там. http://www.openradar.me/radar?id=4999313432248320

Контекст перехода view(forKey:)метод неправильно возвращает nil при определенных обстоятельствах. Похоже, это происходит дляview(forKey: .from)когда представляющий контроллер представления представлен в немодальном режиме. При отклонении контроллера представления, который был первоначально представлен из немодального контроллера представления, результатview(forKey: .to) также равно нулю.

Я наблюдал это не только в новой презентации в виде листов на iPhone, но и в обычных листах и ​​всплывающих окнах на iPad.

Еще одним проявлением этой проблемы, похоже, является то, что finalFrame(for:) метод возвращает неверный CGRectкогда его спросили, каким должен быть последний кадр для этого контроллера представления. В моем тестировании он возвращает полноэкранный прямоугольник, хотя правильный вид меньше.

Обходной путь - использовать корневой контроллер представления контроллера представления, возвращенный viewController(forKey:), хотя документация явно не рекомендует, чтобы: "Представление, возвращаемое этим методом, может быть или не быть корневым представлением соответствующего контроллера представления".

Приведенный выше ответ подходит для установки modalPresentationStyle к .fullScreen, однако также стоит упомянуть, что если ваш контроллер представления встроен в UINavigationController, вам необходимо установить его на контроллере навигации:

navigationController.modalPresentationStyle = .fullScreen

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

У меня есть новые открытия по этой проблеме. Чтобы сослаться на 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" и работать только косвенно.

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

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

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