Hex цвета в Swift: как работает магия #FF5733

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Почему #FF5733 — это не просто случайный набор символов?

Вы когда-нибудь задумывались, что скрывается за привычной записью #FF5733 в вашем коде? Для большинства разработчиков это просто «какой-то оранжево-розовый цвет». Но если копнуть глубже, за этим шестизначным кодом стоит элегантная математика, битовые операции и история, уходящая корнями в старые мониторы и спецификации HTML.

В этой статье мы разберём hex-цвета в Swift с нуля. Вы узнаете, как работают RGB-каналы, почему hex-формат так популярен, и — самое главное — как написать свой собственный UIColor (или Color для SwiftUI), который принимает шестнадцатеричные строки. И да, мы рассмотрим реальный код, который вы сможете использовать прямо сегодня.

Если вы когда-нибудь искали ответ на вопрос «How to use hex color values in Swift» на Stack Overflow — вы попали по адресу. Только теперь с русским переводом и глубоким объяснением.

Анатомия hex-цвета: откуда берутся эти цифры?

Давайте начнём с самого простого. Цвет на экране — это комбинация трёх базовых компонентов: Red (красный), Green (зелёный) и Blue (синий). Каждый из них может принимать значение от 0 до 255. Почему 255? Потому что это максимальное число, которое можно записать в один байт (8 бит).

Hex-формат — это просто компактный способ записи этих трёх чисел.

  • #FF5733 разбивается на три пары: FF, 57, 33.
  • FF в десятичной системе = 255 (максимум красного).
  • 57 = 87 (зелёный).
  • 33 = 51 (синий).
  • Итоговый цвет: RGB(255, 87, 51) — яркий коралловый.

Шестнадцатеричная система (основание 16) использует цифры от 0 до 9 и буквы от A до F. Это позволяет записать число от 0 до 255 всего двумя символами. Удобно, правда?

Почему hex так популярен в вебе и iOS?

Исторически hex-коды пришли из веб-дизайна. Когда CSS только начинал развиваться, #RRGGBB стал стандартом для указания цветов. Swift и UIKit переняли эту традицию, но с одним нюансом: встроенного парсера hex-строк в UIColor нет.

Каждый iOS-разработчик хотя бы раз писал extension для UIColor, который превращает "#FF5733" в UIColor. Это стало своеобразным «ритуалом посвящения». И сегодня мы пройдём этот ритуал вместе.

Пишем свой hex-парсер в Swift (пошагово)

Давайте создадим удобный и безопасный инициализатор для UIColor, который принимает hex-строку. Мы разберём каждый шаг.

Шаг 1: Базовая структура

import UIKit

extension UIColor {
    convenience init?(hex: String) {
        // Здесь будет магия
    }
}

Мы используем convenience init? (проваливающийся), потому что строка может быть невалидной.

Шаг 2: Очищаем строку

Пользователи могут передать "#FF5733", "FF5733" или даже "0xFF5733". Нам нужно убрать всё лишнее.

var hexString = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()

if hexString.hasPrefix("#") {
    hexString.removeFirst()
}

if hexString.hasPrefix("0X") {
    hexString.removeFirst(2)
}

Шаг 3: Проверяем длину

Стандартный hex-код — это 6 символов (RRGGBB). Но есть и 8-символьный формат (RRGGBBAA), где AA — альфа-канал (прозрачность). Мы поддержим оба.

guard hexString.count == 6 || hexString.count == 8 else {
    return nil
}

Шаг 4: Парсим строку в числа

Теперь самое интересное. Нам нужно превратить строку в шестнадцатеричное число, а затем извлечь из него компоненты RGB.

guard let hexValue = UInt64(hexString, radix: 16) else {
    return nil
}

let red, green, blue, alpha: CGFloat

if hexString.count == 6 {
    // Формат RRGGBB — альфа = 1.0
    red   = CGFloat((hexValue >> 16) & 0xFF) / 255.0
    green = CGFloat((hexValue >> 8) & 0xFF) / 255.0
    blue  = CGFloat(hexValue & 0xFF) / 255.0
    alpha = 1.0
} else {
    // Формат RRGGBBAA
    red   = CGFloat((hexValue >> 24) & 0xFF) / 255.0
    green = CGFloat((hexValue >> 16) & 0xFF) / 255.0
    blue  = CGFloat((hexValue >> 8) & 0xFF) / 255.0
    alpha = CGFloat(hexValue & 0xFF) / 255.0
}

self.init(red: red, green: green, blue: blue, alpha: alpha)

Разбираем битовые операции: что здесь происходит?

Если вы не знакомы с побитовыми операциями, этот код может выглядеть как магия. Давайте разложим всё по полочкам.

Представьте, что hexValue — это число 0xFF5733. В двоичном виде это 24 бита:

  • Биты 23-16: красный канал (0xFF)
  • Биты 15-8: зелёный канал (0x57)
  • Биты 7-0: синий канал (0x33)

Операция >> 16 (сдвиг вправо на 16 бит) «сдвигает» красный канал в младшие биты. Теперь число стало 0xFF.

Операция & 0xFF (побитовое И) отсекает всё, кроме последних 8 бит. Если бы мы не сделали этого, при сдвиге на 8 бит могли бы остаться «хвосты» от красного канала.

Результат: мы получаем чистые значения от 0 до 255 для каждого канала. После деления на 255.0 получаем числа от 0.0 до 1.0 — именно то, что ожидает UIColor.

Полный код для копирования

Вот готовый extension, который можно добавить в любой проект:

import UIKit

extension UIColor {
    /// Создаёт UIColor из hex-строки.
    /// Под                

Блоги

Рекомендаций по книгам