Xcode 11.4. Цвет заголовка навигации стал ЧЕРНЫМ от раскадровки

55

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

Вы не можете изменить ни один из кодов, следующая строка кода больше не работает

self.navigationController?.navigationBar.titleTextAttributes = [.foregroundColor: UIColor.white]

Я только заставляю это работать, используя некоторые вещи iOS 13 UINavigationBarAppearance

@available(iOS 13.0, *)
    private func setupNavigationBar() {
        let app = UINavigationBarAppearance()
        app.titleTextAttributes = [.foregroundColor: UIColor.white]
        app.backgroundColor = Constants.Color.barColor
        self.navigationController?.navigationBar.compactAppearance = app
        self.navigationController?.navigationBar.standardAppearance = app
        self.navigationController?.navigationBar.scrollEdgeAppearance = app

        self.navigationController?.navigationBar.titleTextAttributes = [.foregroundColor: UIColor.white]
    }

Может кто-нибудь объяснить мне, почему ??? Это критическая ошибка или какая-то новая скрытая функция?

Тудор Попа
источник
3
Та же проблема здесь, и я не нахожу ничего, чтобы исправить это. Я думаю, что это ошибка: /
Джордан Фаврей
Яблоко. Uggh. В самом деле?
Даниэль
попробуйте это stackoverflow.com/a/61003557/3887987
Амрит Тивари
это обновление интерфейса XCode Bug Обновление XCode до 11.4.1
NinjaDeveloper

Ответы:

36

Это исправило это для меня, используя вместо этого UINavigationBarAppearance из: Настройка панели навигации вашего приложения

if #available(iOS 13.0, *) {
    let appearance = UINavigationBarAppearance()
    appearance.configureWithOpaqueBackground()
    appearance.backgroundColor = UIColor.black
    appearance.titleTextAttributes = [.foregroundColor: UIColor.white] // With a red background, make the title more readable.
    self.navigationBar.standardAppearance = appearance
    self.navigationBar.scrollEdgeAppearance = appearance
    self.navigationBar.compactAppearance = appearance // For iPhone small navigation bar in landscape.
} else {
    self.navigationBar.barTintColor = UIColor.black
    self.navigationBar.tintColor = UIColor.white
    self.navigationBar.titleTextAttributes = [.foregroundColor: UIColor.white]
}

Примечание. Я вложил в класс UINavigationController , и он был вызван из переопределения viewWillAppear .

... или для AppDelegate , для всего приложения:

if #available(iOS 13.0, *) {
    let appearance = UINavigationBarAppearance()
    appearance.configureWithOpaqueBackground()
    appearance.backgroundColor = UIColor.black
    appearance.titleTextAttributes = [
        NSAttributedStringKey.foregroundColor: UIColor.white
    ]

    let buttonAppearance = UIBarButtonItemAppearance()
    buttonAppearance.normal.titleTextAttributes = [.foregroundColor: UIColor.white]
    appearance.buttonAppearance = buttonAppearance

    UINavigationBar.appearance().standardAppearance = appearance
    UINavigationBar.appearance().scrollEdgeAppearance = appearance
    UINavigationBar.appearance().compactAppearance = appearance

    UIBarButtonItem.appearance().tintColor = UIColor.white
} else {
    UINavigationBar.appearance().barTintColor = UIColor.black
    UINavigationBar.appearance().titleTextAttributes = [
        NSAttributedStringKey.foregroundColor: UIColor.white
    ]
    UINavigationBar.appearance().tintColor = UIColor.white

    UIBarButtonItem.appearance().tintColor = UIColor.white
}

... для AppDelegate, для всего приложения, в Objective-C:

if (@available(iOS 13, *)) {
    UINavigationBarAppearance *appearance = [[UINavigationBarAppearance alloc] init];
    [appearance configureWithOpaqueBackground];
    appearance.backgroundColor = UIColor.whiteColor;
    appearance.titleTextAttributes = titleAttributes;

    UIBarButtonItemAppearance *buttonAppearance = [[UIBarButtonItemAppearance alloc] init];
    buttonAppearance.normal.titleTextAttributes = barButtonItemAttributes;
    appearance.buttonAppearance = buttonAppearance;

    UINavigationBar.appearance.standardAppearance = appearance;
    UINavigationBar.appearance.scrollEdgeAppearance = appearance;
    UINavigationBar.appearance.compactAppearance = appearance;

    [[UINavigationBar appearance] setTintColor:UIColor.blackColor];
} else {
    [[UINavigationBar appearance] setBarTintColor:UIColor.whiteColor];
    [[UINavigationBar appearance] setTintColor:UIColor.blackColor];
    [[UINavigationBar appearance] setTranslucent:false];
    [[UINavigationBar appearance] setTitleTextAttributes: titleAttributes];
    [[UIBarButtonItem appearance] setTitleTextAttributes:barButtonItemAttributes forState:UIControlStateNormal];
}
Стю Карни
источник
Спасибо, это правильный ответ! На iOS 13 Apple добавила, UINavigationBarAppearance()и без всякой причины на старом Xcode мы не должны были зависеть от него, но, поскольку Xcode 11.4 должен использовать его, UINavigationBarAppearance()или цвет заголовка всегда будет черным.
Василий
appearance.largeTitleTextAttributesдля больших названий.
Скуа
Это прекрасно работает, и спасибо! Есть ли способ сделать это универсально из AppDelegate?
слайсер
@slicerdicer - Да! Смотрите мой обновленный ответ, например. Приветствия.
Стю Карни
1
@Richard - я только что добавил ответ для Objective-C. Извините, я не видел ваш комментарий до сегодняшнего дня.
Стю Карни
14

На раскадровке для вашего контроллера навигации измените «Bar Tint» на значение «Default», затем в своем коде вы можете изменить его, как обычно.

Судхакар Варма
источник
3
Лучший ответ. В самом деле.
Владимир Пригарин
2
Это правильный путь
Хьюго
1
Лучший период ответа.
shadowsheep
2
@ JCutting8 да, все верно. Но с Xcode 11.4, если вы не установите цвет по умолчанию в раскадровке, изменение его программно не будет работать. Я не знаю, является ли это проблемой или нет.
shadowsheep
1
Это магия!
ekashking
6

Не уверен, что это ошибка или нет.

Мы исправили это, установив «Стиль строки состояния» на темное или светлое содержимое в настройках проекта. Это заставит цвет текста строки состояния определенным образом, а не будет определяться на основе устройств, находящихся в режиме «Светлый» или «Темный».

Кроме того, вам нужно установить значение «Просмотр внешнего вида строки состояния на основе контроллера» на «НЕТ» в вашем Info.plist. без этого значения «Стиль строки состояния» будет переопределен.

Затем создайте пользовательский контроллер навигации и внедрите его в свои раскадровки.

class CustomNavigationController: UINavigationController {

 override func viewDidLoad() {
    super.viewDidLoad()
    setNavBar()
 }

 func setNavBar() {
    if #available(iOS 13.0, *) {
        let appearance = UINavigationBarAppearance()
        appearance.configureWithOpaqueBackground()
        appearance.backgroundColor = UIColor.blue
        appearance.titleTextAttributes = [.foregroundColor: UIColor.yellow]
        self.navigationBar.standardAppearance = appearance
        self.navigationBar.scrollEdgeAppearance = appearance
        self.navigationBar.compactAppearance = appearance
    } else {
        self.navigationBar.barTintColor = UIColor.blue
        self.navigationBar.titleTextAttributes = [.foregroundColor: UIColor.yellow]
    }
  }
}

* Цвета установлены так, чтобы вы могли видеть их четко работающими.

Я обнаружил, что лучше установить код в ViewDidLoad, а не в ViewDidAppear, потому что мои цвета не устанавливались при первоначальной загрузке, только после перехода назад и перезагрузки.

Я также обнаружил, что эта проблема может быть связана с «Bar Tint» NavBar. когда мы впервые пытались ее решить, мы установили «Bar Tint» на значение по умолчанию, и это, похоже, тоже разрешило ошибку. Тем не менее, он сделал это так, что мы не смогли получить цвет фона NavBar, что мы хотели. Поэтому в своих раскадровках я позаботился о том, чтобы установить это значение по умолчанию просто для хорошей меры.

Надеюсь, поможет

jameseronious
источник
Это работает. Кажется, что это просто установка глобального стиля, который не работает.
Монго
определите ошибку на конце яблока. не может не сломать вещи>. <
Майкл МакКенна
2

нет необходимости в workaround.it - ​​это ошибка в Xcode Interface Builder. Apple выпустила обновление для Xcode 11.4.1

из заметок о выпуске разработчика Apple

Интерфейсный Разработчик

Исправлена ​​проблема, из-за которой некоторые свойства внешнего вида UINavigationBar, установленные в раскадровке и документах XIB, игнорировались при сборке с Xcode 11.4. (60883063) (FB7639654)

https://developer.apple.com/documentation/xcode_release_notes/xcode_11_4_1_release_notes

NinjaDeveloper
источник
0

По аналогии с ответом Стю Карни 3/25, я добавил еще несколько деталей реализации.

Создайте подкласс UINavigationController . Добавьте следующее к viewWillAppear:

let isDarkMode = UserDefaults.standard.bool(forKey: "DarkMode")
let titleColor: UIColor = isDarkMode ? .white : .black
let navBarColor: UIColor = isDarkMode ? .black : .white
let tintColor: UIColor = isDarkMode ? .yellow : .red  //back button text and arrow color, as well as right bar button item

if #available(iOS 13.0, *) {
    let appearance = UINavigationBarAppearance()
    appearance.configureWithOpaqueBackground()
    appearance.backgroundColor = navBarColor
    appearance.titleTextAttributes = [.foregroundColor: titleColor]
    appearance.largeTitleTextAttributes = [.foregroundColor: titleColor]

    self.navigationBar.standardAppearance = appearance
    self.navigationBar.scrollEdgeAppearance = appearance
    self.navigationBar.compactAppearance = appearance // For iPhone small navigation bar in landscape.

    self.navigationBar.tintColor = tintColor //changes back button text and arrow color, as well as right bar button item
} else {
    self.navigationBar.barTintColor = navBarColor
    self.navigationBar.tintColor = tintColor
    self.navigationBar.titleTextAttributes = [.foregroundColor: titleColor]
    self.navigationBar.largeTitleTextAttributes = [.foregroundColor: titleColor]
}

Затем переопределите предпочитаемое значение StatusBarStyle :

override var preferredStatusBarStyle: UIStatusBarStyle {
    let isDarkMode = UserDefaults.standard.bool(forKey: "DarkMode")
    return isDarkMode ? .lightContent : .default
}

Если вы хотите динамически обновлять панель навигации и строку состояния, например, с помощью IBAction или метода селектора UISwitch, добавьте следующее:

navigationController?.loadView()
navigationController?.topViewController?.setNeedsStatusBarAppearanceUpdate()

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

Джош Р
источник
0

В моем случае, после того, как я обновил Xcode с 11.3 до 11.4, эта ошибка произошла. Поэтому я должен изменить свой код, чтобы выдуть, чтобы установить изображение в качестве фона на панели навигации.

if #available(iOS 13.0, *) {
    let appearance = UINavigationBarAppearance()
    appearance.configureWithOpaqueBackground()
    let backgroundImage = UIImage(named: "{NAVBAR_IMAGE_NAME}")?.resizableImage(withCapInsets: UIEdgeInsets.zero, resizingMode: .stretch)
    appearance.backgroundImage = backgroundImage
    self.navigationController?.navigationBar.compactAppearance = appearance
    self.navigationController?.navigationBar.standardAppearance = appearance
    self.navigationController?.navigationBar.scrollEdgeAppearance = appearance        
} else {
    self.navigationController?.navigationBar.barTintColor = Utils.themeColor
    let backgroundImage = UIImage(named: "{NAVBAR_IMAGE_NAME}")?.resizableImage(withCapInsets: UIEdgeInsets.zero, resizingMode: .stretch)
    self.navigationController?.navigationBar.setBackgroundImage(backgroundImage, for: .default)
    self.navigationController?.navigationBar.shadowImage = UIImage()
}
Реза Дехнави
источник