Ошибка UIAppearance во время восстановления состояния

Обновлять

Мэтт правильно заметил, что в моем первоначальном проекте была ошибка с восстановлением состояния. Однако даже после его удаления я могу воспроизвести проблему, если использую табличное представление внутри навигационного контроллера и пытаюсь установить свойство isTranslucent UINavigationBar в false через прокси-сервер внешнего вида.


По какой-то причине, когда iOS восстанавливает состояние, UIAppearance переопределяет значения, установленные в viewDidLoad. Это вызывает у меня много головной боли, и я хотел бы знать, как решить эту проблему. Я рассматриваю это как ошибку.

Вот небольшой проект, который я создал на GitHub, чтобы проиллюстрировать эту проблему. Когда вы запускаете его в первый раз, шрифт метки в ViewController правильно установлен на 22 пункта. Однако, если вы инициируете восстановление состояния, это будет 12 баллов из-за метода появления в willFinishLaunching.

На самом деле причина этой проблемы не в UILabel.appearance(whenContainedInInstancesOf: [UITableViewCell.self]).font = UIFont.systemFont(ofSize: 12), как я изначально думал. Вместо этого UINavigationBar.appearance(whenContainedInInstancesOf: [GLXNavigationController.self]).isTranslucent = false вызывает такое поведение. Вы можете легко убедиться в этом сами.

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

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

Любая помощь горячо приветствуется.


person Andriy Gordiychuk    schedule 26.09.2018    source источник
comment
Это может не исправить, но у вас, вероятно, вообще не должно быть didFinishLaunching, а также очень важно, чтобы window?.makeKeyAndVisible() явно отображалось в willFinishLaunching.   -  person matt    schedule 26.09.2018
comment
@matt, ты гений. Перемещение makeKeyAndVisible решает эту проблему. Моя логика размещения его в didFinishLaunching заключалась в том, что если ViewController восстанавливается, нам не нужно его устанавливать. В противном случае, если восстановление состояния не происходит, нам нужно установить его.   -  person Andriy Gordiychuk    schedule 26.09.2018
comment
@matt, что бы вы посоветовали по поводу того, что должно находиться в willFinishLaunching, а что в didFinishLaunching? Я немного борюсь с этим. Весь мой пользовательский интерфейс создается программно   -  person Andriy Gordiychuk    schedule 26.09.2018
comment
Я действительно должен был упомянуть makeKeyAndVisible в своем ответе; Я внесу поправку. — Если вы занимаетесь сохранением и восстановлением состояния, все должно находиться в willFinishLaunching, насколько я понимаю.   -  person matt    schedule 26.09.2018
comment
Кстати, все это есть в моей книге; базовый пример на основе раскадровки здесь: >github.com/mattneub/Programming-iOS-Book-Examples/blob/master/   -  person matt    schedule 26.09.2018
comment
@matt большое спасибо! Должен ли я вызывать makeKeyAndVisible, даже если я использую раскадровки? Я этого не знал... Кроме того, я предполагаю, что могу поместить инициализацию различных сторонних фреймворков (например, firebase) в didFinishLaunching.   -  person Andriy Gordiychuk    schedule 26.09.2018
comment
Должен ли я вызывать makeKeyAndVisible, даже если я использую раскадровки Да.   -  person matt    schedule 26.09.2018


Ответы (1)


Вы неправильно выполняете восстановление состояния:

  • Измените didFinishLaunchingWithOptions на willFinishLaunchingWithOptions.

  • И убедитесь, что willFinishLaunchingWithOptions содержит вызов окна makeKeyAndVisible, даже если больше ничего не содержит.

Это, наряду с реализациями shouldSaveApplicationState и shouldRestoreApplicationState, составляет базовый шаблон, необходимый для любой реализации сохранения и восстановления состояния.

person matt    schedule 26.09.2018
comment
Большое спасибо, это устраняет проблему в пробном проекте. Однако в настоящем мне также пришлось удалить строку UINavigationBar.appearance(whenContainedInInstancesOf: [GLXNavigationController.self]).isTranslucent = false. Я совершенно озадачен тем, почему это так. Однако я не могу воспроизвести эту проблему в небольшом проекте... - person Andriy Gordiychuk; 26.09.2018
comment
Бинго! Я смог воспроизвести это на небольшом проекте. Сейчас опубликую обновление - person Andriy Gordiychuk; 26.09.2018