iPhone: сохранить с проверкой на обратной навигации

В моем приложении для iPhone у меня есть навигационный контроллер, главный экран и несколько экранов редактирования. На экране редактирования пользователь вводит некоторые данные, которые необходимо проверить, прежде чем я смогу их сохранить. В идеале я хотел бы автоматически обновлять данные при обратной навигации без дополнительной кнопки «Готово». Могу ли я выполнить некоторую проверку и сохранить обратную навигацию (т. е. когда пользователь нажимает стандартную кнопку «Назад») таким образом, чтобы я мог остановить навигацию и показать сообщение об ошибке, если что-то не так?

Я вижу несколько других возможностей:

  • Создайте свою пользовательскую левую кнопку и сделайте так, чтобы она выглядела как стандартная. (Почему Apple не поместила этот стиль кнопки в общедоступный API?)
  • Добавьте кнопку «Готово» и сохраните данные, только если пользователь коснется ее

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


person SergGr    schedule 15.12.2009    source источник


Ответы (6)


По сути, вы хотите переопределить действие из backBarButton вашего корневого контроллера представления и выполнить там проверку. Если проверка проходит, вызовите UINavigationController popViewControllerAnimated:, в противном случае покажите предупреждение об ошибке или что-то еще.

Однако, если вы попытаетесь установить свойства target и action для контроллеров корневого представления navigationItem.backBarButton, это не сработает. По-видимому, они должны быть нулевыми.

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

person cidered    schedule 15.12.2009
comment
Это именно то, что я имел в виду как вариант № 1, но если это возможно, мне не нравится имитировать нативный внешний вид. - person SergGr; 15.12.2009

Просто переопределите [popViewControllerAnimated:] в вашем подклассе UIViewController. Таким образом, вы охватываете более общий сценарий выхода контроллера представления из экрана.

person refulgentis    schedule 16.12.2009
comment
Не может этого сделать: popViewControllerAnimated происходит от UINavigationController, а не от UIViewController... ему пришлось бы сделать конкретного (и отдельного) потомка UINavigationController только для этого - вообще не рекомендуется. - person Zoran Simic; 16.12.2009

Лучший способ, который я нашел для «обнаружения нажатия кнопки «Назад», — это переопределить viewWillDisappear следующим образом:

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    if (!isPushing) {
        // Apply your changes here
    }
}

Булево значение isPushing будет тем, которое вы определяете сами, и вы устанавливаете его в True только в тех местах, где вы сами нажимаете другой контроллер (если вы это делаете...), что позволяет вам различать viewWillDisappear, вызываемый из-за того, что вы нажимаете новый контроллер самостоятельно, потому что была нажата кнопка «Назад».

Обычно вы сами вставляете другой контроллер в контроллер таблицы следующим образом:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // Example of pushing a new controller onto the navigation stack yourself...
    isPushing = YES;    // You have to set that boolean here...
    [self.navigationController pushViewController:myNewController animated:YES];
}
person Zoran Simic    schedule 16.12.2009
comment
Я знаю, что могу перехватить событие, дело в том, что я не вижу способа остановить навигацию в этот момент. И если я не могу остановить навигацию, я не могу сделать ничего разумного, если проверка ввода не удалась. - person SergGr; 16.12.2009

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

person Frank Schmitt    schedule 23.12.2009

Альтернативный способ - заставить родительское представление выполнять эту работу.

Допустим, вы переходите от представления данных (например, «Контактная информация») к представлению редактирования поля (например, «Редактирование имени»). Прежде чем перейти к просмотру редактирования, в представлении данных хранится некоторая информация об этом факте, например:

self.navigatingTo = NavigatingToNameEdit;

Затем в представлении данных viewWillAppear проверьте это и извлеките соответствующую информацию из представления редактирования:

if (self.navigatingTo == NavigatingToNameEdit) {
    self.name = self.nameEditView.name;
    // Don't forget to reset navigatingTo:
    self.navigatingTo = NavigatingToNone;
}
person squelart    schedule 24.12.2009

Хотя вы, вероятно, отошли от этого некоторое время назад, я только сегодня столкнулся с этой проблемой. Я предполагаю, что Apple не хочет, чтобы вы переопределяли действие этих кнопок «Назад». Мое решение состояло в том, чтобы отображать и предупреждать представление (которое отображается на контроллере представления, на который вы только что перешли) и использовать метод делегата AlertViews «clickedButtonAtIndex», чтобы вернуть пользователя на экран с ошибками. В целом, я думаю, что это довольно чисто. Мои 2 цента...

person Staros    schedule 12.03.2010