Xcode 11.4. Título da navegação Color gone BLACK do storyboard

55

Atualizei recentemente meu Xcode para 11.4. Quando executo o aplicativo no dispositivo, notei que todos os títulos de meus itens de navegação ficaram totalmente pretos ao serem configurados no storyboard. insira a descrição da imagem aqui

Você não pode mudar nem do código, a seguinte linha de código não funciona mais

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

Eu só faço funcionar usando alguns itens do 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]
    }

Alguém pode me explicar por que ??? Este é um bug crucial ou algum novo recurso oculto?

Tudor Popa
fonte
3
Mesmo problema aqui e não encontro nada para corrigir isso. Eu acho que é um bug: /
Jordan Favray 25/03
Maçã. Uggh. Mesmo?
Daniel
tente este stackoverflow.com/a/61003557/3887987
Amrit Tiwari
é Xcode
Code

Respostas:

36

Isso foi corrigido para mim, usando UINavigationBarAppearance, em: Personalizando a barra de navegação do seu aplicativo

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

Nota: Subclassifiquei UINavigationController e isso foi chamado a partir da substituição de viewWillAppear .

... ou para AppDelegate , em todo o aplicativo:

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
}

... para AppDelegate, em todo o aplicativo, no 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];
}
Stu Carney
fonte
Obrigado, esta é uma resposta correta! , no iOS 13, a Apple adicionou UINavigationBarAppearance()e, sem motivo, no Xcode antigo, não precisamos depender dele, mas desde o Xcode 11.4 ele deve usar UINavigationBarAppearance()ou a cor do título será sempre preta.
Basil
appearance.largeTitleTextAttributespara títulos grandes.
Skoua 26/03
Isso funciona muito bem e obrigado !, Existe alguma maneira de fazer isso universalmente a partir do AppDelegate?
slicerdicer 27/03
@slicerdicer - Sim! Veja minha resposta atualizada, para um exemplo. Felicidades.
Stu Carney
11
@ Richard - Acabei de adicionar a resposta para Objective-C. Desculpe, não vi seu comentário até hoje.
Stu Carney
14

No storyboard, para o seu Navigation Controller, altere o "Bar Tint" para o valor "Default" e, em seu código, você poderá alterá-lo como faria normalmente.

Sudhakar Varma
fonte
3
Melhor resposta. Realmente.
Vladimir Prigarin 30/03
2
Esta é a maneira correta
Hugo
11
Melhor período de resposta.
shadowsheep
2
@ JCutting8 sim, isso mesmo. Mas com o Xcode 11.4, se você não definir a cor padrão no storyboard, alterá-lo programaticamente não funcionará. Não sei se isso é um problema ou não.
shadowsheep
11
Isso é uma mágica!
ekashking 9/04
6

Não tenho certeza se é um bug ou não.

A maneira como corrigimos é configurando o "Estilo da barra de status" para conteúdo escuro ou claro na configuração do projeto. Isso forçará a cor do texto da barra de status de uma certa maneira, em vez de ser determinada com base nos dispositivos que estão no modo Claro ou Escuro.

Além disso, você precisa definir o valor "Visualizar aparência da barra de status com base no controlador" como "NÃO" no seu Info.plist. sem esse valor, o "estilo da barra de status" será substituído.

Em seguida, crie um controlador de navegação personalizado e implemente-o em seus storyboards.

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

* As cores estão definidas para que você possa vê-las claramente funcionando.

Eu achei que era melhor definir o código no ViewDidLoad, em vez do ViewDidAppear, porque minhas cores não estavam sendo definidas no carregamento inicial, somente depois de voltar e recarregar.

Também descobri que esse problema pode estar vinculado ao "Bar Tint" de um NavBar. quando estávamos tentando resolvê-lo, definimos o "Bar Tint" como padrão e isso parecia resolver o erro também. No entanto, ele fez com que não pudéssemos obter a cor de fundo do NavBar como desejávamos. Assim, em meus storyboards, certifiquei-me de definir esse valor como padrão apenas por uma boa medida.

Espero que ajude

jameseronious
fonte
Isso funciona. Parece que está apenas definindo o estilo global que não funciona.
Mongo
def um bug no final da maçã. não posso deixar de quebrar as coisas>. <
Michael McKenna
2

não há necessidade da solução alternativa. é um erro no Xcode Interface Builder. Atualização de lançamento da Apple para o Xcode 11.4.1

das notas de versão do desenvolvedor da Apple

Construtor de interface

Corrigido um problema que fazia com que algumas propriedades de aparência do UINavigationBar definidas no storyboard e nos documentos XIB fossem ignoradas ao criar com o Xcode 11.4. (60883063) (FB7639654)

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

NinjaDeveloper
fonte
0

Semelhante à resposta de Stu Carney em 25/3, adicionei mais alguns detalhes de implementação.

Crie uma subclasse de UINavigationController . Adicione o seguinte a 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]
}

Em seguida, substitua o preferidoStatusBarStyle :

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

Se você deseja atualizar a barra de navegação e a barra de status dinamicamente, como em um método IBAction ou seletor do UISwitch, adicione o seguinte:

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

Além disso, certifique-se de definir todas as suas barras de navegação e botões de barra para as cores padrão no IB. O Xcode parece ter um erro em que as cores do IB substituem as cores programadas.

Josh R
fonte
0

No meu caso, após a atualização do Xcode de 11.3 para 11.4, esse bug ocorreu. Então eu tenho que mudar meu código para explodir, a fim de definir uma imagem como plano de fundo na barra de navegação.

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()
}
Reza Dehnavi
fonte