Отключение контроллера представления данных

У меня есть теоретический вопрос. Теперь я читаю Apple ViewController.

Они написали:

Когда приходит время отклонить представленный контроллер представления, предпочтительный подход заключается в том, чтобы позволить диспетчеру представления зрения отклонить Это. Другими словами, по возможности, тот же контроллер представленный диспетчер представлений, должен также взять на себя ответственность за увольняя его. Хотя существует несколько способов уведомления представление контроллера представления, что его представленный контроллер представления должен быть отклоненным, предпочтительным методом является делегирование.

Но я не могу объяснить, почему я должен создать протокол в представленном VC и добавить varate varate, создать метод делегирования при представлении VC для отклонения представленного VC вместо простого вызова в представленном метод контроллера просмотра

[self dismissViewControllerAnimated:NO completion:nil]?

Почему первый выбор лучше? Почему Apple рекомендует его?

Ответ 1

Я думаю, что Apple немного закрывает свои спины для потенциально кудрявой части API.

  [self dismissViewControllerAnimated:NO completion:nil]

На самом деле это немного скрипка. Хотя вы можете - на законных основаниях - называть это на представленном контроллере представления, все, что он делает, - это переслать сообщение на контроллер представления. Если вы хотите сделать что-то сверх того, просто отклонив VC, вам нужно будет это знать, и вам нужно относиться к нему так же, как к методу делегата, - как это в значительной степени, что это такое, запеченный в несколько негибкий делегата.

Возможно, они столкнулись с множеством плохого кода людьми, которые не понимают, как это объединяется, поэтому их осторожность.

Но, конечно, если все, что вам нужно сделать, это отказаться от этой вещи, продолжайте.

Мой собственный подход - это компромисс, по крайней мере, это напоминает мне, что происходит:

  [[self presentingViewController] dismissViewControllerAnimated:NO completion:nil]

[Свифт]

  self.presentingViewController?.dismiss(animated: false, completion:nil)

Ответ 2

Это для повторного использования контроллера просмотра.

Контроллер вашего представления не должен заботиться о том, будет ли он представлен как модальный, нажат на контроллер навигации или что-то еще. Если ваш контроллер просмотра отклоняется от себя, то вы предполагаете, что он представлен модально. Вы не сможете нажать этот контроллер просмотра на контроллер навигации.

Посредством реализации протокола вы позволяете контроллеру родительского представления решать, как его следует отображать/отталкивать и отклонять/выскакивать.

Ответ 3

Обновлен для Swift 3

Я пришел сюда, просто желая отклонить текущий (представленный) View Controller. Я делаю этот ответ для всех, кто приходит сюда с той же целью.

Контроллер навигации

Если вы используете навигационный контроллер, это довольно просто.

Вернитесь к предыдущему контроллеру представления:

// Swift
self.navigationController?.popViewController(animated: true)

// Objective-C
[self.navigationController popViewControllerAnimated:YES];

Вернитесь к контроллеру корневого представления:

// Swift
self.navigationController?.popToRootViewController(animated: true)

// Objective-C
[self.navigationController popToRootViewControllerAnimated:YES];

(Спасибо этот ответ для Objective-C.)

Модальный контроллер просмотра

Когда диспетчер представлений представлен модально, вы можете отклонить его (со второго контроллера представления), вызвав

// Swift
self.dismiss(animated: true, completion: nil)

// Objective-C
[self dismissViewControllerAnimated:YES completion:nil];

documentation говорит,

Контроллер представления представления отвечает за отклонение представления который он представил. Если вы вызываете этот метод на представленном представлении сам контроллер, UIKit просит обработчик представления представления обрабатывать увольнение.

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

Делегаты

Вопрос OP заключался в сложности использования делегатов для отклонения представления.

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

Ответ 4

По моему опыту, он пригодится, когда вам нужно уволить его из любого ViewController, который вы хотите, и выполнять разные задачи для каждого диспетчера представлений, который его отклоняет. Любой viewController, который принимает протокол, может отклонить представление по-своему. (ipad vs iphone или передача разных данных при отклонении от разных представлений, вызов различных методов при отклонении и т.д.)

Edit:

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

Ответ 5

попробуйте следующее:

[self dismissViewControllerAnimated:true completion:nil];

Ответ 6

Цитата из View Руководство по программированию контроллера, "Как диспетчеры просмотра представляют другие контроллеры просмотра".

Каждый контроллер представления в цепочке представленных контроллеров представлений имеет указатели на другие объекты, окружающие его в цепочке. В других слова, представленный контроллер представления, который представляет другое представление контроллер имеет действительные объекты как в своем представленииViewController, так и в Представлены свойстваViewController. Вы можете использовать эти отношения для проследите через контроллеры цепи зрения по мере необходимости. Например, если пользователь отменяет текущую операцию, вы можете удалить все объекты в цепочку, отклонив первый представленный контроллер представления. Отключение контроллера вида отклоняет не только этот контроллер представления но и любые контроллеры представлений, которые он представил.

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

Хотя, я лично предпочел бы использовать разматывающие сегменты, чем попытаться пройти назад дерево представлений представлений, о чем говорит Apple в этой главе, в которой содержится цитата.

Ответ 7

Один момент заключается в том, что это хороший подход к кодированию. Он удовлетворяет многим принципам OOP, например, SRP, Разделение проблем и т.д.

Таким образом, диспетчер представлений, представляющий представление, должен быть тем, кто его отклоняет.

Как, компания по продаже недвижимости, которая дает дом в аренду, должна быть уполномочена вернуть его.

Ответ 8

Swift 3.0 //Dismise View Controller в быстром

self.navigationController?.popViewController(animated: true)
dismiss(animated: true, completion: nil)

Ответ 9

Если вы используете опцию использования модального использования.

[self dismissViewControllerAnimated:NO completion:nil];

Ответ 10

Это очень много. Делегирование прекрасное, когда это необходимо, но если он делает код более сложным - и он это делает - тогда для этого должна быть причина.

Я уверен, что у Apple есть свои причины. Но яснее и понятнее просто предоставить представленный VC увольнение, если нет истинной причины для этого, и никто из нас здесь не представил того, что я вижу.

Протоколы превосходны, когда они необходимы, но объектно-ориентированный дизайн никогда не связан с тем, что модули обмениваются без необходимости друг с другом.

Tom Love (со-разработчик Objective C) однажды прокомментировал, что Objective C был "элегантным", "маленьким", "четким" и "четко определенным" (при сравнении с С++). Легко ему сказать. Делегирование - это полезная функция, которая, кажется, была чрезмерно использована "только потому, что", и, хотя мне нравится работать на этом языке, я боюсь идеи рубок, вынужденной использовать ненужный синтаксис, чтобы сделать вещи более сложными, чем они должны быть.

Ответ 11

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

Say ViewControllerA представляет ViewControllerB модально. Но, поскольку вы, возможно, не написали код для ViewControllerA, вы не знаете жизненный цикл ViewControllerA. Он может отклонить 5 секунд (скажем) после представления вашего контроллера вида ViewControllerB.

В этом случае, если вы просто использовали dismissViewController из ViewControllerB для отклонения от себя, вы попали бы в состояние undefined - возможно, это не авария или черный экран, а состояние undefined из вашей точки зрения.

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

Ответ 12

Свифта

let rootViewController:UIViewController = (UIApplication.shared.keyWindow?.rootViewController)!

        if (rootViewController.presentedViewController != nil) {
            rootViewController.dismiss(animated: true, completion: {
                //completion block.
            })
        }