Приобретение интерактивного пакетаPopGestureRecognizer отклоняет обратный вызов/событие

Есть ли чистое решение при получении обратного вызова или события на диспетчере просмотра, который отклоняется (выталкивается) с помощью interactivePopGestureRecognizer?

Чтобы быть ясным, мне нужно, чтобы какой-то явный метод вызывался в верхнем большинстве контроллеров (и ни один другой), прежде чем контроллер будет выбит этим распознавателем жестов. Я не хочу получать событие на контроллере навигации и отправлять событие на соответствующий контроллер, и я не хочу использовать viewWillAppear или viewWillDissapear...

Самое близкое, что у меня есть, это добавление пары цель/селектор в жест, имеющий только 2 проблемы. Сначала я не могу получить прямую информацию, если контроллер будет уволен или нет (UIGestureRecognizerStateEnded будет срабатывать в любом случае). Во-вторых, после отклонения контроллера мне нужно удалить цель из распознавателя.

Причиной этого является наличие нескольких контроллеров, которым необходимо отправить некоторую информацию своим делегатам. С помощью кнопок "done" и "cancel" событие запускается, вызываются методы делегирования, а затем вызывается контроллер. Мне нужно примерно то же самое, что и с минимальными изменениями кода.

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

Ответы

Ответ 1

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

Objective-C

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated

Swift

func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool)

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

Objective-C

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
        id<UIViewControllerTransitionCoordinator> tc = navigationController.topViewController.transitionCoordinator;
        [tc notifyWhenInteractionEndsUsingBlock:^(id<UIViewControllerTransitionCoordinatorContext> context) {
            NSLog(@"Is cancelled: %i", [context isCancelled]);
    }];
}

Swift

func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
    if let coordinator = navigationController.topViewController?.transitionCoordinator() {
        coordinator.notifyWhenInteractionEndsUsingBlock({ (context) in
            print("Is cancelled: \(context.isCancelled())")
        })
    }
}

Обратный вызов срабатывает, когда пользователь поднимает свой палец, и (Objec-C) [context isCancelled]; (Swift) context.isCancelled() вернет YES/true, если анимация была отменена (контроллер просмотра не был всплыт), else NO/false. В context есть больше вещей, которые могут быть полезны, как и используемые контроллеры представлений, так и процент анимации, которая была завершена после выпуска и т.д.

Ответ 2

Swift 4 iOS 7 - 10

func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {

    if let coordinator = navigationController.topViewController?.transitionCoordinator {
        coordinator.notifyWhenInteractionEnds({ (context) in
            print("Is cancelled: \(context.isCancelled)")
        })
    }
}

Swift 4/5 iOS 10+

func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {

    if let coordinator = navigationController.topViewController?.transitionCoordinator {
        coordinator.notifyWhenInteractionChanges { (context) in
            print("Is cancelled: \(context.isCancelled)")
        }
    }
}

Ответ 3

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {

    void (^popInteractionEndBlock)(id<UIViewControllerTransitionCoordinatorContext>) =
    ^(id<UIViewControllerTransitionCoordinatorContext> context){
        if (context.completionVelocity >= 1.0f) {
            // complete
        }
    };
    if (@available(iOS 10,*)) {
        [self.navigationController.transitionCoordinator notifyWhenInteractionChangesUsingBlock:popInteractionEndBlock];
    } else {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
        [self.navigationController.transitionCoordinator notifyWhenInteractionEndsUsingBlock:popInteractionEndBlock];
#pragma GCC diagnostic pop
    }
}