Как использовать hex-значения цветов в Swift (UIColor)?
Решение: Extension для UIColor с hex-инициализатором
Самый популярный и удобный способ — добавить свой инициализатор через extension к UIColor. Это позволит создавать цвета одной строкой кода. Ниже — проверенное решение, которое поддерживает форматы #RGB, #RRGGBB, #RRGGBBAA (с альфа-каналом) и вариант без решётки.
import UIKit
extension UIColor {
/// Создаёт UIColor из hex-строки.
/// - Parameter hex: строка вида "#RRGGBB" или "#RRGGBBAA" (решетка опциональна)
/// - Returns: UIColor или .clear при ошибке
convenience init?(hex: String) {
var hexSanitized = hex.trimmingCharacters(in: .whitespacesAndNewlines)
hexSanitized = hexSanitized.replacingOccurrences(of: "#", with: "")
var rgb: UInt64 = 0
guard Scanner(string: hexSanitized).scanHexInt64(&rgb) else { return nil }
let length = hexSanitized.count
let r, g, b, a: CGFloat
switch length {
case 6: // #RRGGBB
r = CGFloat((rgb & 0xFF0000) >> 16) / 255.0
g = CGFloat((rgb & 0x00FF00) >> 8) / 255.0
b = CGFloat(rgb & 0x0000FF) / 255.0
a = 1.0
case 8: // #RRGGBBAA
r = CGFloat((rgb & 0xFF000000) >> 24) / 255.0
g = CGFloat((rgb & 0x00FF0000) >> 16) / 255.0
b = CGFloat((rgb & 0x0000FF00) >> 8) / 255.0
a = CGFloat(rgb & 0x000000FF) / 255.0
default:
return nil
}
self.init(red: r, green: g, blue: b, alpha: a)
}
}
Как это работает
- Очистка строки: удаляем пробелы и символ
#, если он есть. - Парсинг: используем
Scannerдля преобразования hex-строки в 64-битное число. - Извлечение компонентов: с помощью битовых масок (
0xFF0000и т.д.) получаем значения красного, зеленого, синего и альфа-канала. - Нормализация: делим на 255, чтобы получить диапазон 0.0–1.0, который ожидает
UIColor.
Примеры использования
// Без альфа-канала
let redColor = UIColor(hex: "#FF5733")!
// С альфа-каналом (полупрозрачный)
let semiTransparentBlue = UIColor(hex: "#3498DB80")! // 50% прозрачности
// Без решётки
let greenColor = UIColor(hex: "27AE60")!
// Использование для фона кнопки
button.backgroundColor = UIColor(hex: "#2ECC71")
Важные замечания
- Инициализатор помечен как
failable(?) — если строка некорректна, вернётсяnil. Используйте force unwrap (!) только когда уверены в данных. - Для iOS 13+ можно использовать
UIColor(dynamicProvider:)для адаптации к тёмной теме, комбинируя с этим extension. - Если вам нужно много цветов, вынесите их в константы или enum для переиспользования.
Этот подход — стандарт в iOS-сообществе и используется тысячами разработчиков. Он простой, надёжный и покрывает 99% случаев работы с hex-цветами.
<<Альтернативный подход: Использование CGFloats и Int
Если вы предпочитаете работать с целыми числами вместо строк, можно создать инициализатор, принимающий hex-значение как Int. Это удобно, когда цвета заданы в коде как константы.
extension UIColor {
convenience init(hex: Int, alpha: CGFloat = 1.0) {
let r = CGFloat((hex & 0xFF0000) >> 16) / 255.0
let g = CGFloat((hex & 0x00FF00) >> 8) / 255.0
let b = CGFloat(hex & 0x0000FF) / 255.0
self.init(red: r, green: g, blue: b, alpha: alpha)
}
}
// Использование:
let color = UIColor(hex: 0x3498DB)
let semiTransparent = UIColor(hex: 0xE74C3C, alpha: 0.7)
Когда это лучше?
- Если вы храните цвета в
enumили константах как Int (например,static let primaryColor = 0x2ECC71). - Когда не нужна поддержка строковых форматов — это быстрее и безопаснее.
- Для задания прозрачности отдельным параметром, а не внутри hex.
Оба подхода имеют право на жизнь. Строковый вариант гибче для пользовательского ввода, числовой — компактнее для кода. Выбирайте под свою задачу!