PreviewProvider — что это, протокол SwiftUI и настройка в Xcode

Автор: IT Sectr Опубликовано: 2026-06-27 Время чтения: 10 мин

PreviewProvider — протокол SwiftUI, который определяет точку входа для генерации превью в Xcode Canvas. Реализация протокола позволяет разработчику увидеть интерфейс без запуска симулятора, ускоряя итерацию на этапе вёрстки. По данным Apple Developer Documentation (2026), PreviewProvider обязателен для всех SwiftUI View, если проект использует Canvas — без него Canvas не отображает пользовательский интерфейс. Узнайте больше в статье о SwiftUI.

Главное

  • PreviewProvider — протокол SwiftUI для генерации Xcode Preview в Canvas.
  • Одно требование — протокол содержит единственное вычисляемое свойство previews: some View.
  • Множественные превью — через Group можно отобразить несколько состояний одной View.
  • Device-конфиги — previewDevice, previewLayout и displayName настраивают отображение.
  • UIKit-совместимость — UIViewRepresentable и UIViewControllerRepresentable также поддерживают PreviewProvider.

Что такое PreviewProvider?

PreviewProvider — протокол SwiftUI, определяющий контракт для создания превью-контента в Xcode Canvas. Протокол содержит единственное обязательное свойство: previews типа some View. Любое значение, возвращаемое previews, отображается в Canvas как интерактивная превью. PreviewProvider не требует наследования — достаточно статической реализации в extension.

Архитектурно PreviewProvider не является частью рантайма SwiftUI — это исключительно инструмент разработки. Протокол маркирован атрибутом @available(iOS 13.0, *) и не компилируется в релизную сборку, так как Xcode использует conditional compilation для исключения превью-кода из production. Это значит, что PreviewProvider не влияет на размер бинарника и производительность приложения.

Протокол previews

Свойство previews — единственное требование PreviewProvider. Оно должно возвращать любую View: от простого Text до сложной иерархии с Group и ForEach. Xcode рендерит возвращённую View в Canvas, применяя системные настройки (тему, размер, шрифт).

swift
import SwiftUI

struct GreetingView: View {
    let name: String
    
    var body: some View {
        Text("Hello, \(name)!")
            .padding()
    }
}

// PreviewProvider — static implementation
struct GreetingView_Previews: PreviewProvider {
    static var previews: some View {
        GreetingView(name: "World")
    }
}

Конвенция именования: Apple рекомендует называть структуру превью как {ViewName}_Previews. Это не является обязательным требованием компилятора, но улучшает читаемость и навигацию по проекту. Xcode автоматически подставляет этот шаблон при создании нового SwiftUI файла.

Как работает PreviewProvider: протокол и метод previews

Механизм работы PreviewProvider основан на статической диспетчеризации: Xcode компилирует extension с PreviewProvider только для Debug-конфигурации и вызывает previews в процессе построения Canvas. Каждый раз при изменении кода Xcode перекомпилирует только изменённые PreviewProvider, что обеспечивает near-instant preview обновление.

SwiftUI не гарантирует точное соответствие превью финальному UI на симуляторе или устройстве — Canvas использует упрощённый рендеринг. Анимации с задержками могут отображаться некорректно, а некоторые UIKit-компоненты (MapKit, WebView) не рендерятся в Canvas без дополнительной настройки.

Множественные превью через Group

Group позволяет отобразить несколько состояний одной View одновременно, что ускоряет итерацию при верстке различных конфигураций. Каждое превью внутри Group рендерится независимо.

swift
struct ButtonView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            ButtonView(title: "Primary", style: .primary)
                .previewDisplayName("Primary")
            
            ButtonView(title: "Disabled", style: .primary)
                .disabled(true)
                .previewDisplayName("Disabled")
            
            ButtonView(title: "Secondary", style: .secondary)
                .previewDisplayName("Secondary")
        }
    }
}

previewDisplayName добавляет подпись к каждому превью в Canvas, что особенно удобно при сравнении нескольких состояний. Максимальное количество превью в Group не ограничено, но более 6–8 замедляют Canvas.

Настройка превью в Xcode

Xcode предоставляет несколько модификаторов для настройки отображения превью. Основные: previewDevice — эмулирует конкретное устройство (iPhone 16 Pro, iPad Air, Apple Watch Ultra), previewLayout — задаёт размер (device, fixed, sizeThatFits). Комбинация этих модификаторов даёт полный контроль над превью-окружением.

previewDevice принимает строку с именем устройства, например "iPhone 16 Pro" или "iPad Pro 13-inch (M4)". Список доступных устройств зависит от установленных симуляторов в Xcode. Если устройство не найдено, Canvas отображает превью на устройстве по умолчанию без ошибки.

МодификаторОписаниеПример
previewDeviceЭмуляция устройства.previewDevice("iPhone 16 Pro")
previewLayoutРежим размера.previewLayout(.sizeThatFits)
previewDisplayNameПодпись превью.previewDisplayName("Dark Mode")
preferredColorSchemeТема оформления.preferredColorScheme(.dark)
dynamicTypeSizeРазмер шрифта.dynamicTypeSize(.xxxLarge)

Превью для разных устройств

Распространённая практика — показывать одну View на нескольких устройствах одновременно, чтобы проверить адаптивность. Для этого используется ForEach с массивом имён устройств.

swift
struct AdaptiveView_Previews: PreviewProvider {
    static var previews: some View {
        ForEach(["iPhone SE (3rd generation)", "iPhone 16 Pro Max", "iPad Pro 13-inch (M4)"], id: \.self) { device in
            AdaptiveView()
                .previewDevice(.previewDevice(device))
                .previewDisplayName(device)
        }
    }
}

Примеры PreviewProvider

Практические примеры показывают различные сценарии использования PreviewProvider: от простого превью до сложных конфигураций с live-данными и UIKit-совместимостью.

Превью с мок-данными

Мок-данные — стандартный паттерн для превью, когда View принимает модель. Вместо реального API подставляются тестовые данные, что позволяет визуально проверить состояние UI без запуска приложения.

swift
struct UserProfileView: View {
    let user: User
    
    var body: some View {
        VStack {
            AsyncImage(url: user.avatarURL)
                .clipShape(Circle())
            Text(user.name)
                .font(.title)
            Text(user.bio)
                .font(.body)
                .foregroundColor(.secondary)
        }
    }
}

struct UserProfileView_Previews: PreviewProvider {
    static var previews: some View {
        UserProfileView(user: .mock)
            .previewDisplayName("Profile")
        
        UserProfileView(user: .mockLongName)
            .previewDisplayName("Long Name")
    }
}

UIKit-превью через UIViewRepresentable

UIKit-совместимость — PreviewProvider работает и с UIKit-компонентами, обёрнутыми в UIViewRepresentable. Это позволяет превьюрить существующие UIKit-вью в SwiftUI Canvas без миграции всего проекта.

swift
struct MapViewRepresentable: UIViewRepresentable {
    func makeUIView(context: Context) -> MKMapView {
        MKMapView()
    }
    
    func updateUIView(_ uiView: MKMapView, context: Context) {
        // Configure map
    }
}

struct MapView_Previews: PreviewProvider {
    static var previews: some View {
        MapViewRepresentable()
    }
}

PreviewProvider и SwiftUI Canvas

Canvas — это визуальный редактор Xcode, который рендерит результат работы PreviewProvider в реальном времени. Без реализации PreviewProvider Canvas остаётся пустым. Canvas и PreviewProvider работают в паре: PreviewProvider определяет что показывать, Canvas — где и как.

Важно понимать: Canvas — это среда выполнения превью, а не альтернатива PreviewProvider. Даже если разработчик не открывает Canvas, PreviewProvider может использоваться для быстрой проверки кода через всплывающее превью при наведении на иконку Canvas. По данным WWDC 2024, Apple рекомендует писать PreviewProvider для каждой View как стандарт разработки, аналогичный написанию unit-тестов.

КомпонентРольОбязательность
PreviewProviderОпределяет контент превьюОбязателен для Canvas
CanvasРендерит превью в редактореОпционален (можно использовать .preview)
SwiftUI ViewUI-компонентОбязателен

Рекомендация: пишите PreviewProvider для каждой публичной View в проекте. Это ускоряет онбординг новых разработчиков, упрощает code review и позволяет быстро проверять визуальные изменения без сборки всего проекта.

Типичные проблемы с PreviewProvider

Проблема 1: Preview не обновляется. Если Canvas не отражает изменения кода, причина чаще всего в кэше DerivedData. Очистите DerivedData через Product → Clean Build Folder (⇧⌘K) или вручную удалив папку ~/Library/Developer/Xcode/DerivedData. После очистки Canvas перестраивает превью заново.

Проблема 2: PreviewProvider не видит @StateObject. PreviewProvider создаёт статический экземпляр View, поэтому зависимости, требующие инъекции (ViewModels, сервисы), должны передаваться через инициализатор или @StateObject с дефолтным значением. Используйте мок-объекты вместо реальных сервисов в превью.

Проблема 3: Анимации не работают в Canvas. Canvas не поддерживает все анимации SwiftUI — особенно те, что зависят от времени (withAnimation с задержкой, .spring). Для проверки анимаций запускайте приложение на симуляторе. Canvas подходит для статической проверки layout.

Исправление PreviewProvider с зависимостями

Инъекция зависимостей — лучший способ сделать PreviewProvider рабочим со сложными ViewModel. Создайте отдельный экземпляр ViewModel с тестовыми данными и передайте его в инициализатор View.

swift
struct DashboardView: View {
    @StateObject var viewModel: DashboardViewModel
    
    var body: some View {
        List(viewModel.items) { item in
            Text(item.title)
        }
    }
}

struct DashboardView_Previews: PreviewProvider {
    static var previews: some View {
        DashboardView(viewModel: DashboardViewModel.mock)
    }
}

Mock-расширения: создайте extension для ViewModel, который предоставляет статические .mock экземпляры. Это держит тестовые данные рядом с ViewModel и делает PreviewProvider читаемым.

Часто задаваемые вопросы

Обязательно ли писать PreviewProvider для каждой View?

Технически нет — приложение скомпилируется и без PreviewProvider. Однако на практике Apple и сообщество SwiftUI рекомендуют писать превью для каждой публичной View. PreviewProvider ускоряет разработку, позволяет быстро проверять layout под разными устройствами и служит визуальной документацией для команды.

Почему PreviewProvider иногда показывает ошибку компиляции?

PreviewProvider добавляет код только в Debug-сборку, поэтому ошибки компиляции могут возникать, если в превью используются типы, недоступные в релизной конфигурации. Также ошибки возникают при использовании @available с платформами, не поддерживающими Canvas, или при превышении лимита сложности превью.

Как передать данные из API в PreviewProvider?

Напрямую — никак, PreviewProvider выполняется в изоляции. Используйте мок-данные: создайте статический extension модели с .mock-экземплярами. Для View с @StateObject передавайте ViewModel с тестовыми данными через инициализатор. Это имитирует реальные данные без сетевых запросов.

Влияет ли PreviewProvider на размер итогового IPA?

Нет, PreviewProvider не влияет на размер релизного бинарника. Xcode использует conditional compilation (#if DEBUG / #if !RELEASE) для исключения превью-кода из релизной сборки. PreviewProvider-код присутствует только в Debug-конфигурации и не попадает в App Store билд.

Можно ли отлаживать PreviewProvider в Xcode?

Да, Xcode поддерживает отладку превью. Установите breakpoint внутри previews или самого кода View и выберите Product → Preview → Debug Preview. После этого breakpoint сработает при рендеринге Canvas. Это полезно для анализа layout issues, которые видны только в превью.

Итоги

  • PreviewProvider — протокол SwiftUI для создания превью в Xcode Canvas с единственным свойством previews.
  • Множественные превью — Group с ForEach позволяет отобразить несколько состояний View на разных устройствах.
  • Модификаторы — previewDevice, previewLayout, preferredColorScheme и dynamicTypeSize настраивают отображение.
  • Изоляция — PreviewProvider работает только в Debug-конфигурации и не влияет на размер релизного IPA.
  • Мок-данные — для превью со сложными моделями используйте статические .mock-экземпляры.
  • UIKit поддержка — через UIViewRepresentable PreviewProvider работает и с UIKit-компонентами.

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также