Introdução: por que essa maldita linha não deixa os desenvolvedores dormirem?
\n\nSe você já tentou fazer o design de um aplicativo "como no Apple Music" ou "como no Telegram" — com certeza já se deparou com isso. Você cria um UINavigationBar perfeito com um belo gradiente, transparência ou cor personalizada, executa o simulador — e vê aquela linha fina cinza ou preta (1 pixel) na parte inferior. Ela parece um artefato, como sujeira no vidro. E sim, ela irrita.
Essa linha de 1px não é um bug, é uma funcionalidade. É a shadowImage + backgroundImage que a Apple, por algum motivo, deixou como padrão. Mesmo no iOS 17 ela ainda aparece, a menos que você diga ao sistema: "Ei, tire isso". A pergunta no Stack Overflow sobre esse assunto tem milhares de visualizações e dezenas de respostas. Ou seja, o tema é realmente problemático.
\n\nNeste artigo, mostrarei 3 abordagens funcionais em Swift para ocultar a linha inferior do UINavigationBar. Vamos analisar tanto os métodos antigos (iOS 13-) quanto os modernos através do UINavigationBarAppearance. Vamos lá!
Método 1: Clássico — através de backgroundImage e shadowImage
\n\nO método mais antigo e comprovado. Funciona desde o iOS 5 (sim, desde a época em que o skeuomorfismo estava na moda). A ideia é simples: definimos uma imagem vazia como fundo e sombra.
\n\nPasso 1: Criar uma imagem vazia
\n\nextension UIImage {\n static func pixelImage(withColor color: UIColor = .clear) -> UIImage {\n let rect = CGRect(x: 0, y: 0, width: 1, height: 1)\n UIGraphicsBeginImageContext(rect.size)\n color.setFill()\n UIRectFill(rect)\n let image = UIGraphicsGetImageFromCurrentImageContext()\n UIGraphicsEndImageContext()\n return image ?? UIImage()\n }\n}\n\nPasso 2: Aplicar ao navigationBar
\n\nfunc hideBottomLine() {\n let emptyImage = UIImage.pixelImage()\n navigationController?.navigationBar.setBackgroundImage(emptyImage, for: .default)\n navigationController?.navigationBar.shadowImage = emptyImage\n}\n\nVantagens: Funciona em qualquer lugar, mesmo em iOS antigos.
\nDesvantagens: Nem sempre funciona corretamente com scrollEdgeAppearance e títulos grandes. Se você tiver uma UISearchBar — a linha pode voltar.
Método 2: Moderno — através de UINavigationBarAppearance (iOS 13+)
\n\nA partir do iOS 13, a Apple apresentou o UINavigationBarAppearance. É um objeto único que gerencia todos os estados: padrão, scroll e compacto. Ideal para quem quer "configurar uma vez e esquecer".
Exemplo completo para UIViewController
\n\nfunc setupTransparentNavigationBar() {\n let appearance = UINavigationBarAppearance()\n appearance.configureWithTransparentBackground()\n appearance.backgroundColor = .clear\n appearance.shadowColor = .clear // remove a linha\n \n navigationController?.navigationBar.standardAppearance = appearance\n navigationController?.navigationBar.scrollEdgeAppearance = appearance\n navigationController?.navigationBar.compactAppearance = appearance\n}\n\nObserve: shadowColor = .clear — esta é a linha chave. Se não escrevê-la, a linha permanecerá. O configureWithTransparentBackground() torna o fundo transparente, mas não mexe na sombra.
Se você precisar de um fundo colorido, mas sem a linha:
\n\nlet appearance = UINavigationBarAppearance()\nappearance.configureWithOpaqueBackground()\nappearance.backgroundColor = .systemBlue\nappearance.shadowColor = .clear\n\nnavigationController?.navigationBar.standardAppearance = appearance\nnavigationController?.navigationBar.scrollEdgeAppearance = appearance\n\nVantagens: Código limpo, fácil de combinar com títulos grandes e pesquisa.
\nDesvantagens: Apenas iOS 13+. Se o projeto suportar iOS 12 — virá