Где в жизненном цикле представления обновлять контроллер после закрытия модального UIViewController

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

На моем экране модальных настроек у меня есть UISegmentedControl, чтобы пользователь мог выбирать единицы измерения. Всякий раз, когда он изменяется, эта функция обновляет userDefaults:

  func saveUnitsSelection() {
    if unitsControl.selectedSegmentIndex == 0 {
      UserDefaultsManager.sharedInstance.preferredUnits = Units.pounds.rawValue
    } else {
      UserDefaultsManager.sharedInstance.preferredUnits = Units.kilograms.rawValue
    }
  }

Тогда они, скорее всего, закроют экран настроек. Итак, я добавил это к viewDidLoad в моем первом контроллере представления:

override func viewDidLoad() {
  super.viewDidLoad()

  let preferredUnits = UserDefaultsManager.sharedInstance.preferredUnits
  units.text = preferredUnits 
}

Это не сработало, поэтому я переместил его на viewWillAppear(), и это тоже не сработало. Я провел некоторое исследование и отладку пещерного человека и обнаружил, что ни одна из этих функций не вызывается после того, как представление было загружено/представлено в первый раз. Кажется, что viewWillAppear будет вызываться во второй раз, если я работаю в иерархии UITableViewController, управляемой UINavigationController, но не вызывается, когда я закрываю свой модальный UIViewController, чтобы показать UIViewController под ним.

Изменить 1: вот иерархия представлений, с которой я работаю: введите здесь описание изображения

Я немного застрял на этом этапе и не знаю, что делать дальше.

Редактировать 2: пользователь может нажать кнопку «Готово» на панели навигации, и когда они это сделают, функция dismissSettings() закроет представление «Настройки»:

class SettingsViewController: UITableViewController {

  let preferredUnits = UserDefaultsManager.sharedInstance.preferredUnits
   // some other variables set here

  override func viewDidLoad() {
    super.viewDidLoad()

    self.navigationController?.navigationBar.topItem?.title = "Settings"

    navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Done", style: .Plain, target: self, action: #selector(self.dismissSettings(_:)))

    if preferredUnits == Units.pounds.rawValue {
      unitsControl.selectedSegmentIndex = 0
     } else {
       unitsControl.selectedSegmentIndex = 1
     }
   }

  func dismissSettings(sender: AnyObject?) {
    navigationController?.dismissViewControllerAnimated(true, completion: nil)

  }
}

person Jim    schedule 05.08.2016    source источник
comment
Где вы добавили func viewDidLoad()? Если бы это было в контроллере представления, Xcode должен пожаловаться, что вы не объявили override, и вы должны вызвать super. Интересно, вы добавляете код не в тот класс?   -  person Aaron Brager    schedule 05.08.2016
comment
Кроме того, можете ли вы подробно описать иерархию представлений нижележащего контроллера представлений? Это внутри контроллера навигации и / или вкладок?   -  person Aaron Brager    schedule 05.08.2016
comment
Прости за это, @AaronBrager. viewDidLoad находится в первом контроллере представления. И я по ошибке удалил override и super.viewDidLoad, когда удалил кучу лишнего кода. Я исправил это выше. Я также добавил скриншот иерархии представлений.   -  person Jim    schedule 05.08.2016


Ответы (1)


НАСТОЯЩАЯ ПРОБЛЕМА

Вы написали с ошибкой viewWillAppear. Вы назвали это:

func viewWillAppear()

Что касается Cocoa Touch, это случайная нерелевантная функция, которая ни к чему не привязывается. Вы имели в виду:

override func viewWillAppear(animated: Bool)

Полное имя первой функции: "viewWillAppear"

Полное имя второй функции: "viewWillAppear:animated"

Как только вы привыкнете к этому, экстремальный метод «перегрузки», который использует Cocoa Touch, станет проще.

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

Другой урок, который каждый должен усвоить при публикации вопроса: включите весь связанный код!

Полезная функция ведения журнала, которую я использую вместо печати или NSLog, чтобы помочь найти следующие вещи:

class Util {
    static func log(message: String, sourceAbsolutePath: String = #file, line: Int = #line, function: String = #function, category: String = "General") {
        let threadType = NSThread.currentThread().isMainThread ? "main" : "other"
        let baseName = (NSURL(fileURLWithPath: sourceAbsolutePath).lastPathComponent! as NSString).stringByDeletingPathExtension ?? "UNKNOWN_FILE"
        print("\(NSDate()) \(threadType) \(baseName) \(function)[\(line)]: \(message)")
    }
}

[Остальное предыдущее обсуждение удалено, так как это были неверные предположения]

person BaseZen    schedule 05.08.2016
comment
Вы правы, это переход Show (например, Push) между контроллером начального представления (Calculator) и контроллером навигации, но я обещаю, что он поднимается снизу и охватывает весь вид, когда нажимается кнопка «Настройки» и перемещается вниз к исчезают при нажатии кнопки «Готово». Чтобы устранить неполадки, я поместил print (я сделал это для viewWillAppear() внутри `viewWillAppear()' начального контроллера представления, и он не печатает второй раз, когда настройки закрываются. Как вы распечатывали такие события? Я попробую, может быть, это мне что-то скажет. - person Jim; 05.08.2016
comment
Но мне все еще нужно увидеть ваш код увольнения - аналог того, что есть у меня. - person BaseZen; 05.08.2016
comment
И мой код отклонения отличается от вашего, так что вы пробовали? - person BaseZen; 05.08.2016
comment
Ой, я не уловил эту разницу в коде отклонения. Я изменил его сейчас в Edit 2. К сожалению, поведение остается прежним. - person Jim; 05.08.2016
comment
Отлично работает для меня, копируя ваш код дословно. Мне было бы любопытно посмотреть, в чем проблема. Возможно, повреждена раскадровка. Сделать чистку/сборку? Можете ли вы загрузить весь свой проект куда-нибудь? - person BaseZen; 05.08.2016
comment
Вот ссылка: github.com/JCMcLovin/onerepmax/tree/upload-to- github Кроме того, я выполнил очистку и сборку, но никаких изменений в поведении. Когда вы запустите его, обратите внимание на метку единиц измерения в первой сцене, коснитесь «Настройки» в левом верхнем углу, измените единицы измерения в сцене «Настройки», затем нажмите «Готово». Вы увидите, что метка не изменилась, и вы видите, что viewDidLoad() не вызывается во второй раз. Большое спасибо, что нашли время, чтобы посмотреть на это для меня. - person Jim; 05.08.2016
comment
Нашел его из вашего github, см. новое решение - person BaseZen; 06.08.2016
comment
Ничего себе, я не знаю, поймал бы я это когда-нибудь. Спасибо. Что касается этой утилиты отладки, я получил этот код до того, как вы его удалили, чтобы я мог попробовать его сам, потому что он выглядит очень полезным. Но я получил несколько неразрешенных ошибок идентификатора в Util и использование «журнала» члена экземпляра в Util в ObservingVC. Я вернул его на github в отключенном состоянии. Я знаю, что это больше, чем я должен спросить, но если вам так хочется, не могли бы вы потратить 2 минуты, чтобы посмотреть и сказать мне, где я ошибаюсь? Я очень благодарен за вашу помощь в любом случае. - person Jim; 06.08.2016
comment
Функция ведения журнала добавлена ​​​​обратно к ответу. Каким-то образом ваша подпись func тоже была искажена. Не уверен, что это был ты или я. - person BaseZen; 06.08.2016