Как использовать hex-коды цветов (HEX Color) в Swift и UIColor?
Правильная реализация HEX-цветов в Swift
Ваша проблема в том, что вы не удаляете символ # из строки перед сканированием. Когда Scanner встречает решётку, он не может распарсить hex-число, и возвращает 0. Вот исправленное и улучшенное решение с обработкой ошибок:
import UIKit
extension UIColor {
/// Инициализация UIColor из hex-строки
/// - Parameters:
/// - hex: Строка вида "#RRGGBB" или "RRGGBB" (регистр не важен)
/// - alpha: Прозрачность (0.0...1.0), по умолчанию 1.0
convenience init?(hex: String, alpha: CGFloat = 1.0) {
// 1. Удаляем пробелы и символ #
var hexSanitized = hex.trimmingCharacters(in: .whitespacesAndNewlines)
hexSanitized = hexSanitized.replacingOccurrences(of: "#", with: "")
// 2. Проверяем длину (должна быть 6 символов для RGB)
guard hexSanitized.count == 6 else {
print("Ошибка: hex-строка должна содержать 6 символов (RRGGBB)")
return nil
}
// 3. Парсим hex-строку в UInt64
var rgbValue: UInt64 = 0
let scanner = Scanner(string: hexSanitized)
guard scanner.scanHexInt64(&rgbValue) else {
print("Ошибка: не удалось распарсить hex-строку")
return nil
}
// 4. Извлекаем компоненты RGB
let red = CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0
let green = CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0
let blue = CGFloat(rgbValue & 0x0000FF) / 255.0
// 5. Инициализируем UIColor
self.init(red: red, green: green, blue: blue, alpha: alpha)
}
}
Использование
// Базовое использование
let orangeColor = UIColor(hex: "#FF5733")!
let blueColor = UIColor(hex: "3366FF")!
// С прозрачностью
let semiTransparentGreen = UIColor(hex: "#00FF00", alpha: 0.5)!
// Безопасное извлечение (guard)
guard let customColor = UIColor(hex: "#AABBCC") else {
print("Неверный hex-код")
return
}
view.backgroundColor = customColor
Дополнительные возможности
Вы можете расширить функциональность, добавив поддержку:
- Коротких hex-кодов (3 символа):
#F00→#FF0000 - RGBA (8 символов):
#FF573380(последние 2 символа — alpha) - Статических свойств:
UIColor.customOrange
Встроенное решение в iOS 13+
Начиная с iOS 13, Apple добавила удобный инициализатор UIColor(hex:) для SwiftUI. Но в UIKit вам всё равно понадобится своя реализация. Если вы используете SwiftUI, просто пишите:
import SwiftUI
struct ContentView: View {
var body: some View {
Color(hex: "#FF5733")
.frame(width: 100, height: 100)
}
}
Важно: Всегда используйте failable инициализатор (с вопросительным знаком), чтобы избежать крашей при неверном формате. И не забывайте удалять символ # перед парсингом!
Альтернативный подход: использование UInt32 и битовых масок
Вместо строк можно работать с числовыми значениями hex-цветов. Это удобно, если вы храните цвета в конфигурационных файлах или получаете их из API в виде чисел:
extension UIColor {
convenience init(hexValue: UInt32, alpha: CGFloat = 1.0) {
let red = CGFloat((hexValue & 0xFF0000) >> 16) / 255.0
let green = CGFloat((hexValue & 0x00FF00) >> 8) / 255.0
let blue = CGFloat(hexValue & 0x0000FF) / 255.0
self.init(red: red, green: green, blue: blue, alpha: alpha)
}
}
// Использование
let redColor = UIColor(hexValue: 0xFF0000)
let purpleColor = UIColor(hexValue: 0x800080, alpha: 0.8)
Плюсы и минусы
- + Быстрее, чем парсинг строк
- + Нет проблем с символом #
- - Менее читаемо, чем строковые hex-коды
- - Требует конвертации из строки, если данные приходят в текстовом формате
Я рекомендую использовать оба подхода в вашем проекте: строковый для UI-компонентов и числовой для програмно задаваемых цветов. Главное — всегда проверяйте входные данные и используйте failable инициализаторы.
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги
Dependency Injection в Rust: Полное руководство для разработчиков