Добавить объявление

Swift макросы: решение для повторяющегося кода

Всем привет! Сегодня поговорим о Swift макросах: одной из самых мощных фич в Swift. Эта функциональность появилась относительно недавно, но уже успела показать себя как инструмент, который может кардинально изменить подход к написанию кода.

Зачем нужны макросы:


Представьте: вы постоянно пишете однотипный текст с одинаковым стилем в SwiftUI. Код повторяется, а любое изменение темы требует правки в десятках мест. Макросы решают именно эту проблему!

Пример:

// Вместо этого громоздкого блока кода, где нужно прописывать
// все модификаторы вручную для каждого заголовка:
Text("Привет, мир!")
.font(.title)
.fontWeight(.bold)
.foregroundColor(.primary)
.multilineTextAlignment(.center)
.padding(.bottom, 8)

// Мы можем написать просто одну строку с макросом,
// который автоматически развернется во всю необходимую верстку:
@TitleText("Привет, мир!")

Как это работает под капотом:


Создаем объявление макроса, которое говорит компилятору,
что когда он встречает @TitleText, нужно обратиться к внешней реализации:

@freestanding(expression)
public macro TitleText(_ content: String) -> some View = #externalMacro(
module: "MacroToolsMacros",
type: "TitleTextMacro"
)

И саму реализацию макроса, которая генерирует конечный код:

public struct TitleTextMacro: ExpressionMacro {
public static func expansion(
of node: MacroExpansionExprSyntax,
in context: some MacroExpansionContext
) throws -> ExprSyntax {
// Проверяем, что макросу передали строковый аргумент
guard let firstArg = node.argumentList.first?.expression else {
throw CustomMacroError("Нужен текст для заголовка")
}

// Возвращаем готовый код, который заменит вызов макроса
// Компилятор буквально подставит этот текст вместо @TitleText("Привет, мир!")
return """
Text(\(firstArg))
.font(.title)
.fontWeight(.bold)
.foregroundColor(.primary)
.multilineTextAlignment(.center)
.padding(.bottom, 8)
"""
}
}

Что происходит при компиляции:


  • Компилятор встречает @TitleText("Привет, мир!").

  • Вызывает TitleTextMacro.expansion().

  • Получает сгенерированный код с полноценным текстом.

  • Подставляет этот код вместо вызова макроса.


Более сложный пример:

// Превращается в полноценный Text с форматированием
@GreetingText("Мобильный трудоголик")

Здесь макрос не просто подставляет готовый шаблон, а анализирует переданный текст и генерирует разное форматирование в зависимости от содержимого. Например:

  • Если передано имя пользователя: добавляет иконку человека.

  • Если передана профессия: применяет специальное форматирование.

  • Анализирует длину текста и выбирает оптимальный размер шрифта.

  • Может добавлять дополнительные элементы (эмодзи, разделители).


Такой макрос содержит сложную логику разбора и преобразования текста, а не просто подставляет статический шаблон.

Плюсы использования макросов:


  • Ускорение разработки: меньше шаблонного кода.

  • Единообразие UI: все кнопки выглядят одинаково.

  • Компиляция быстрее: макросы раскрываются на этапе компиляции.

Минусы:


  • Дебаггинг превращается в ад: ошибки показываются в сгенерированном коде.

  • Инструменты рефакторинга не работают: Xcode не видит внутрь макросов.

  • Сложность написания: нужно разбираться в SwiftSyntax.

Вывод:


Макросы - это как суперспособность. Мощно, но опасно. Используйте их там, где действительно нужно убрать повторяющийся код и стандартизировать UI.
12.10.2025 9 472