Приобретение интерактивного пакета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
}
}