Хобрук: Ваш путь к мастерству в программировании

Невозможно обновить пользовательский интерфейс в основном потоке с помощью didSet swift

Я пытаюсь обновить UILabel и UIImageView в основном потоке, но это не работает.

У меня есть два ViewController (здесь я назову их ChooseCountryVC и DisplayCountryVC), и в ChooseCountryVC пользователь может выбрать страну, которая ему нравится, а в DisplayCountryVC я хочу отображать название страны в метке и флаг страны в imageView.

Основной технологический процесс приведен ниже.

  1. Нажмите кнопку «Выбрать страну» в DisplayCountryVC.
  2. Представьте ChooseCountryVC, который в основном представляет собой tableView всех стран, и пользователь может выбрать страну.
  3. Когда пользователь выбирает страну, установите свойство «countryCode» в DisplayCountryVC и закройте ChooseCountryVC, чтобы вернуться в DisplayCountryVC.
  4. В функции didSet для «countryCode» в DisplayCountryVC добавьте процесс обновления пользовательского интерфейса в основной поток.

Пример кода, относящийся к этому вопросу, приведен ниже.

●Выберите странуВК

       // when user has chosen a country and dismiss this VC
        let displayCountryVC = DisplayCountryVC()
        displayCountryVC.countryCode = self.chosenCountryCode
        self.dismiss(animated: true, completion: nil) // go back to DisplayCountryVC

●DisplayCountryVC

 var countryCode: String? {
    didSet {
        guard let countryCode = countryCode else {return}
        let countryName = self.getCountryName(with: countryCode) // this function provides countryName with no problem
        let flagImage = self.getFlag(with: countryCode) // this function provides flag image with no problem
        DispatchQueue.main.async {
            self.imageView.image = flagImage 
            self.label.text = countryName
            print("label's text is", self.label.text) // somehow, this prints out country's name correctly in console but apparently UI has not been updated at all
        }
    }
}

Если кто-нибудь знает, что не так с моими кодами или нуждается в дополнительной информации, пожалуйста, дайте мне знать.


  • DispatchQueue.main.async здесь не нужен. Вы все еще находитесь в основном потоке, когда назначаете displayCountryVC.countryCode. Как вы представляете свою DisplayCountryVC? Вы исполняете segue? Убедитесь, что flagImage и countryName не равны нулю 17.01.2020
  • @tuyen Спасибо за ваш комментарий. Сначала я так подумал, поэтому я написал код без DispatchQueue.main.async, но он не работал, поэтому я добавил его. Кроме того, DisplayVC является начальным контроллером представления, и когда пользователь нажимает кнопку в VC, я программно представляю ChooseCountryVC с помощью функции present. Я убедился, что flagImage и countryName не равны нулю, но все равно не отображаются в представлении. 17.01.2020
  • Значит didSet не выполнялось, если нет DispatchQueue.main.async? И почему вы dismiss ChooseCountryVC после предъявления DisplayCountryVC. Есть ли причина? 17.01.2020
  • @tuyenle didSet выполняется без DispatchQueue.main.async , и если я печатаю текст метки в закрытии didSet, он печатает правильную строку в консоли, но не в представлении. 17.01.2020
  • если он печатает правильную строку в консоли, то какой текст вы получаете в представлении? 17.01.2020
  • @tuyenle ничего не показывает в представлении, но я понял, как решить эту проблему с ответом ниже. Спасибо большое за вашу помощь! 17.01.2020

Ответы:


1
 // when user has chosen a country and dismiss this VC
        let displayCountryVC = DisplayCountryVC()
        displayCountryVC.countryCode = self.chosenCountryCode
        self.dismiss(animated: true, completion: nil) // go back to DisplayCountryVC

Здесь вы запускаете новый контроллер представления и устанавливаете для него значение.

Ваш selectedCountryCode установлен на НОВЫЙ контроллер представления, а не на исходный DisplayCountryVC.

После закрытия ChooseCountryVC вы вернетесь к исходному DisplayCountryVC. Этот новый DisplayCountryVC НЕ представлен и не используется.

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

17.01.2020
  • О, я совсем забыл, что отсылал к оригинальному венчурному капиталу, не представляя его! Я решил эту проблему благодаря этому. Огромное спасибо :) 17.01.2020
  • Новые материалы

    Прогресс в технологии Трансформеров часть 3
    Многомасштабный управляющий сигнальный преобразователь для бесфазного синтеза движения (arXiv) Автор: Линтао Ван , Кун Ху , Лей Бай , Юй Дин , Ваньли Оуян , Чжиюн Ван . Аннотация:..

    Представляем поддержку компонентов Vue.js. Мгновенный HMR и многое другое.
    Хотя у FuseBox уже был плагин Vue, он был базовым и не имел многих функций, которые делали работу с Vue.js такой приятной. Однако с этим выпуском мы рады сообщить, что в FuseBox..

    Приключения в Javascript, часть 1
    Я продолжаю думать о том, чтобы писать больше, но чем больше я думаю об этом, тем меньше я это делаю. Итак, сегодня я перестал думать и начал писать. Отсюда можно только спускаться… В..

    Понимание дженериков в TypeScript: подробное руководство
    Введение TypeScript, строго типизированный надмножество JavaScript, хорошо известен своей способностью улучшать масштабируемость, удобочитаемость и ремонтопригодность приложений. Одной из..

    Учебные заметки JavaScript Object Oriented Labs
    Вот моя седьмая неделя обучения программированию. После ruby ​​и его фреймворка rails я начал изучать самый популярный язык интерфейса — javascript. В отличие от ruby, javascript — это более..

    Разбор строк запроса в vue.js
    Иногда вам нужно получить данные из строк запроса, в этой статье показано, как это сделать. В жизни каждого дизайнера/разработчика наступает момент, когда им необходимо беспрепятственно..

    Предсказание моей следующей любимой книги 📚 Благодаря данным Goodreads и машинному обучению 👨‍💻
    «Если вы не любите читать, значит, вы не нашли нужную книгу». - J.K. Роулинг Эта статья сильно отличается от тех, к которым вы, возможно, привыкли . Мне очень понравилось поработать над..