Условное изменение между дочерними представлениями в PageView - PullRequest
1 голос
/ 03 мая 2019

У меня есть PageViewController, P , который содержит два дочерних ViewController, A и B A , и B позволяют пользователю вводить некоторые данные в форму.Если пользователь начинает редактировать форму, я отслеживаю логическую переменную:

var formEdited = false;

В случае, если пользователь хотел бы отойти от формы, а formEdited - true, я бы хотелпредупредите их и скажите «Вы уверены, что хотите отказаться от изменений, внесенных в форму?».Если они уверены, я бы хотел сохранить их данные.В противном случае, я бы позволил им отбросить данные и продолжить их смахиванием.

В результате я попытался сделать что-то подобное в обоих A и B :

 override func viewWillDisappear(_ animated: Bool) {
    if (formEdited) {
        let dialogMessage = UIAlertController(title: "Confirm", message: "Are you sure you want to abandon the changes you have in the form?", preferredStyle: .alert);
        let ok = UIAlertAction(title: "OK", style: .default, handler: { (action) -> Void in
            super.viewWillDisappear(animated);
        })
        let cancel = UIAlertAction(title: "Cancel", style: .cancel) { (action) -> Void in
            // TODO:: what to do here
            self.myCustomFuctionToStoreData(); 
            super.viewWillAppear(true);

        }
        dialogMessage.addAction(ok);
        dialogMessage.addAction(cancel);
        self.present(dialogMessage, animated: true, completion: nil);
    }
}

В результате я вижу свое всплывающее окно, когда пытаюсь провести пальцем в сторону от просмотра.Если я нажму «Отмена», вид останется.(Это то, что я хочу) Однако, если я снова попытаюсь провести пальцем, я больше не вижу окно с предупреждением, и пользовательский интерфейс меняется.(Это не то, что я хочу. Я хочу, чтобы это повторилось)

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

// TODO:: what to do here

Примечание: я пробовал ответы из нескольких других постов, например: Как отключить свайпжест UIPageViewController? , Отключить жест смахивания в UIPageViewController или даже эти два: Отключить UIPageViewController Swipe - Swift и Проверка того, что UIViewController собирается получить Popped изстек навигации? .

Последние два могут быть наиболее подходящими, но я не хочу отключать какие-либо жесты, и при этом я не вижу, как я могу ввести предупреждение.Я просто хочу сделать смахивание от дочернего представления условной функцией.Как бы я сделал это из моего дочернего представления (потомка PageView) в Swift 4?

1 Ответ

0 голосов
/ 12 мая 2019

Оказывается, что реализация операций условной прокрутки в UIPageView тривиальна. Вот шаги, которые я предпринял, чтобы решить проблему. (Обновления этого кода для повышения его эффективности приветствуются)

Для начала ваш UIPageViewController не должен быть источником данных. Это означает, что во время ваших операций прокрутки в дочерних контроллерах представления ничего не будет регистрироваться. (Что сейчас нормально) Вместо этого вы захотите реализовать логику, для которой представление отображается в виде функций, которые могут вызываться дочерними элементами. Эти два метода могут быть добавлены в ваш UIPageView:

func goToNextView(currentViewController : UIViewController) {
    var movingIdx = 0;
    let viewControllerIndex = orderedViewControllers.index(of: currentViewController) ?? 0;
    if (viewControllerIndex + 1 <= (orderedViewControllers.count - 1)) {
        movingIdx = viewControllerIndex + 1;
    }
    self.setViewControllers([orderedViewControllers[movingIdx]], direction: .forward, animated: true, completion: nil);
}

func goToPreviousView(currentViewController : UIViewController) {
    var movingIdx = 0;
    let viewControllerIndex = orderedViewControllers.index(of: currentViewController) ?? -1;
    if (viewControllerIndex == -1) {
        movingIdx = 0;
    } else if (viewControllerIndex - 1 >= 0) {
        movingIdx = viewControllerIndex - 1;
    } else {
        movingIdx = orderedViewControllers.count - 1;
    }
    self.setViewControllers([orderedViewControllers[movingIdx]], direction: .reverse, animated: true, completion: nil);
}

Примечания:

Имеет смысл обновить строки, содержащие ?? 0; способ выдать ошибку или показать экран по умолчанию.

ordersViewControllers - это список всех дочерних представлений, которые этот контроллер UIPageView содержит

Эти методы будут вызываться из дочерних представлений, поэтому их хранение на этом уровне делает их многократно используемыми

Наконец, в представлениях вашего ребенка вам понадобится способ распознавать жесты и реагировать на них:

override func viewDidLoad() {
    super.viewDidLoad();

    let swipeLeft = UISwipeGestureRecognizer(target: self, action: #selector(handleGesture))
    swipeLeft.direction = .left
    self.view.addGestureRecognizer(swipeLeft)

    let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(handleGesture))
    swipeRight.direction = .right
    self.view.addGestureRecognizer(swipeRight)

}

И обработать жест:

@objc func handleGesture(gesture: UISwipeGestureRecognizer) -> Void {
    if gesture.direction == UISwipeGestureRecognizerDirection.left {
        parentPageViewController.goToNextView(currentViewController: self);
    }
    else if gesture.direction == UISwipeGestureRecognizerDirection.right {
        parentPageViewController.goToPreviousView(currentViewController: self);
    }
}

Примечания:

В функции handleGesture вы добавили бы свои условные проверки, чтобы определить, в порядке ли goToNextView или goToPreviousView.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...