Всем привет! Сегодня поговорим о
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.