Указание поведения кнопки «Назад» для каждого контроллера представления

У меня есть несколько контроллеров представления, назовите их 1,2,3,4,5 и 6. Я сделал UINavigationController и у него есть кнопка «Назад». Кнопка «Назад» появляется на каждом контроллере представления (я никогда ее не скрываю).

У меня сейчас такая ситуация. Я перехожу от 1,2,3,4,5, затем обратно к 3. В качестве дополнительной информации, переход от 5 к 3 выполняется с помощью ручного перехода (но иногда я использую другие переходы, например, push или модальные). Если я нажму кнопку «Назад» на этом контроллере представления, обычно он будет равен 5 из-за того, как работает стек. Но я хочу иметь возможность указать, что из контроллера представления 3 вы всегда переходите к vc 2 при нажатии кнопки «Назад»...

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


person Whirlwind    schedule 15.08.2016    source источник


Ответы (4)


Вы можете создать подкласс и переопределить некоторые методы в UINavigationController для получить обратный вызов при нажатии кнопки «Назад». Затем вы можете заставить навигационный контроллер реагировать так, как вы хотите.

Например, когда вызывается popViewController(animated:), вы можете определить на основе контроллеров представления (или как хотите), действительно ли вы должны разрешить обычную функциональность кнопки «Назад». Если вы хотите нормального поведения, просто вызовите super. В случае перехода от контроллера представления 3 к контроллеру представления 2 (вместо контроллера представления 5) вы не будете вызывать super, а вместо этого сделаете popToViewController(viewController2, animated: animated).

person keithbhunter    schedule 15.08.2016
comment
В итоге я сделал это так... Пробовал другие способы, но это было проще и проще всего реализовать. По крайней мере для меня. - person Whirlwind; 16.08.2016
comment
Я только что заметил предупреждение в консоли, в котором говорится: Завершение навигационного перехода в неожиданном состоянии. Дерево подпредставления панели навигации может быть повреждено. Это происходит, если я делаю popToViewController(vc2, анимированный:анимированный). Если я установлю для анимации значение false, сообщение исчезнет, ​​но кнопка «Назад» также исчезнет. Я предполагаю, что это своего рода состояние гонки. Любая идея, как избавиться от этого сообщения, не теряя кнопку «Назад»? - person Whirlwind; 16.08.2016

Обычно, когда я хочу «прыгнуть» назад более чем на одно представление, я использую «делегирование». То, что вы действительно хотите сделать, это вытащить несколько из стека, а не просто перейти туда, куда вы хотите пойти.

Я бы порекомендовал делегировать метод для каждого виртуального канала, который проходит через него. т.е. VC 1 может отклонить VC 2, VC 2 может отклонить VC 3 и т. д. Затем, когда вы находитесь на VC 5, вы вызываете navigationToView (index: Int), вы делаете быструю проверку, и если они просматривают контроллер, который отвечает на этот вызов делегата, соответствует этому индексу затем вы просто открываете ранее отображаемый VC, и все в порядке. Если нет, вы выталкиваете ранее отображаемый VC, а затем вызываете этот метод делегата VC, пока не доберетесь до того места, где хотите быть.

Обычный шаблон проектирования заключается в том, что VC, который отвечает за отображение другого VC, определяет, следует ли его закрыть. Это также дает вам возможность обновлять пользовательский интерфейс, если это необходимо, прежде чем вернуться к предыдущим представлениям.

Надеюсь, это имеет смысл и поможет.

person Skyler Lauren    schedule 15.08.2016

замените кнопку «Назад» своей собственной кнопкой, и вы можете установить действие для выполнения перехода обратно на 3. Или вы можете использовать дочерний стек навигационных контроллеров, чтобы вернуться к 3, что вы предпочитаете.

в контроллере представления добавьте этот код:

let backButton: UIBarButtonItem = UIBarButtonItem(title: "Back", style: .plain, target: self, action: #selector(viewController.navigationController?.popViewController(animated:)))

    viewController.navigationItem.setLeftBarButton(backButton, animated: true)

В настоящее время действие будет использовать поведение по умолчанию и вернется к одному из них. Однако вы можете изменить это с помощью своего собственного метода и выполнить переход обратно к 3.

person torinpitchers    schedule 15.08.2016
comment
Я просто удалил свой комментарий, потому что он неактуален. Я неверно истолковал то, что вы имели в виду под segue, так что теперь я понимаю, о чем вы говорите. - person Whirlwind; 15.08.2016

Предположим, вы открыли ВК 1, 2, 3, 4, 5. Затем вы открыли ВК 3. Итак, у вас есть такой UINavigationController controllers стек [1, 2, 3, 4, 5, 3]

Если вы хотите иметь обратный переход к UIViewController #3, вы можете просто удалить контроллеры #3, #4 и #5 (из середины вашего стека навигации) в момент окончания перехода #3.

func viewDidLoad() {
       self.navigationController.delegate = self
}

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

    NSMutableArray *allViewControllers = [NSMutableArray arrayWithArray: navigationController.viewControllers];
//Navigation stack now is [1, 2, 3, 4, 5, 3]. removing VC #3
        [allViewControllers removeObjectAtIndex: 2];

//Navigation stack now is [1, 2, 4, 5, 3]. removing VC #4
        [allViewControllers removeObjectAtIndex: 2];

//Navigation stack now is [1, 2, 5, 3].removing VC #5
        [allViewControllers removeObjectAtIndex: 2];

//Navigation stack now is [1, 2, 3]
navigationController.viewControllers = allViewControllers;

}

Удалив контроллеры представления из стека навигации, вы вернетесь к переходу с 3 на 2.

person Alexander Tkachenko    schedule 15.08.2016