Xcode 11.4. Цвет заголовка навигации стал ЧЕРНЫМ от раскадровки - PullRequest
55 голосов
/ 25 марта 2020

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

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

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]
    }

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

Ответы [ 7 ]

36 голосов
/ 26 марта 2020

Это исправило это для меня, используя вместо этого 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];
}
14 голосов
/ 28 марта 2020

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

8 голосов
/ 16 апреля 2020

Apple наконец исправила это в версии 11.4.1

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

6 голосов
/ 26 марта 2020

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

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

Кроме того, вам нужно установить значение «Просмотр внешнего вида строки состояния на основе контроллера» на «НЕТ» в вашем 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, что мы хотели. Поэтому в своих раскадровках я позаботился о том, чтобы установить это значение по умолчанию просто для хорошей меры.

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

2 голосов
/ 17 апреля 2020

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

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

Interface Builder

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

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

0 голосов
/ 21 апреля 2020

В моем случае, после того, как я обновил 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()
}
0 голосов
/ 04 апреля 2020

По аналогии с ответом Стю Карни 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
}

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

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

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

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