15 промтов для Swift и iOS: SwiftUI, UIKit, Core Data и Combine — готовая подборка для разработчиков

Введение

Разработка под iOS — это постоянный поиск баланса между производительностью, читаемостью кода и скоростью итераций. SwiftUI обещает декларативную магию, UIKit остаётся стандартом для сложных интерфейсов, Core Data хранит данные миллионов пользователей, а Combine управляет асинхронностью. Но даже опытный iOS-разработчик тратит часы на шаблонные задачи: настройка Core Data стека, обработка ошибок в SwiftUI Preview, создание кастомных анимаций или отладка Combine pipeline.

В этой подборке — 15 проверенных промтов, которые я использую ежедневно. Каждый промт — это конкретная задача, решение с кодом и пояснением. Никакой воды, только рабочие примеры. Вы сможете скопировать их в свой проект или адаптировать под свои нужды.

1. SwiftUI: быстрая настройка Preview с мок-данными

Промт: "Создай SwiftUI Preview для списка задач с использованием мок-объекта TaskViewModel, который возвращает 5 тестовых задач без реального сетевого запроса."

Пример кода:

struct TaskListView_Previews: PreviewProvider {
    static var previews: some View {
        let mockVM = TaskViewModel()
        mockVM.tasks = [
            Task(id: 1, title: "Купить молоко", isDone: false),
            Task(id: 2, title: "Написать статью", isDone: true)
        ]
        return TaskListView(viewModel: mockVM)
    }
}

Пояснение: Этот промт помогает избежать зависимости от реальных данных при разработке UI. Вместо того чтобы каждый раз запускать симулятор, вы получаете мгновенную обратную связь в Canvas. Для продакшена используйте фабрику моков.

2. UIKit: кастомный UICollectionView с CompositionalLayout

Промт: "Напиши UICollectionView с CompositionalLayout, который отображает две секции: первая — горизонтальный список (carousel), вторая — вертикальная сетка 2 колонки. Ячейки — UINib."

Пример кода:

let layout = UICollectionViewCompositionalLayout { sectionIndex, _ in
    if sectionIndex == 0 {
        let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.8), heightDimension: .fractionalHeight(1.0))
        let item = NSCollectionLayoutItem(layoutSize: itemSize)
        let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.8), heightDimension: .absolute(200))
        let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
        let section = NSCollectionLayoutSection(group: group)
        section.orthogonalScrollingBehavior = .continuous
        return section
    } else {
        let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.5), heightDimension: .absolute(150))
        let item = NSCollectionLayoutItem(layoutSize: itemSize)
        item.contentInsets = NSDirectionalEdgeInsets(top: 4, leading: 4, bottom: 4, trailing: 4)
        let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(150))
        let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
        return NSCollectionLayoutSection(group: group)
    }
}

Пояснение: CompositionalLayout гибок, но его синтаксис легко забыть. Этот промт — шпаргалка для создания сложных макетов без Storyboard.

3. Core Data: настройка стека с NSPersistentContainer

Промт: "Создай синглтон CoreDataManager с NSPersistentContainer, поддержкой миграций и фоновым контекстом для записи."

Пример кода:

final class CoreDataManager {
    static let shared = CoreDataManager()
    let container: NSPersistentContainer

    private init() {
        container = NSPersistentContainer(name: "Model")
        container.loadPersistentStores { _, error in
            if let error = error { fatalError("Ошибка Core Data: \(error)") }
        }
        container.viewContext.automaticallyMergesChangesFromParent = true
    }

    var backgroundContext: NSManagedObjectContext {
        return container.newBackgroundContext()
    }
}

Пояснение: Этот промт — стандартный boilerplate для Core Data. Используйте backgroundContext для записи, чтобы не блокировать UI.

4. Combine: обработка поискового запроса с debounce

Промт: "Реализуй поиск в UITextField с помощью Combine: debounce 300 мс, отмена предыдущего запроса и обновление результатов на главном потоке."

Пример кода:

import Combine

class SearchViewModel: ObservableObject {
    @Published var query: String = ""
    @Published var results: [String] = []
    private var cancellables = Set<AnyCancellable>()

    init() {
        $query
            .debounce(for: .milliseconds(300), scheduler: RunLoop.main)
            .removeDuplicates()
            .sink { [weak self] text in
                // Здесь ваш сетевой запрос
                self?.results = ["Результат для: \(text)"]
            }
            .store(in: &cancellables)
    }
}

Пояснение: debounce сокращает количество запросов при быстром вводе. removeDuplicates предотвращает повторные запросы с тем же текстом.

5. SwiftUI: кастомный модификатор для загрузки изображений

Промт: "Создай ViewModifier для асинхронной загрузки изображения по URL с placeholder и обработкой ошибок."

Пример кода:

struct AsyncImageModifier: ViewModifier {
    let url: URL?
    @State private var image: UIImage? = nil

    func body(content: Content) -> some View {
        content.overlay(
            Group {
                if let image = image {
                    Image(uiImage: image).resizable()
                } else {
                    ProgressView()
                }
            }
        )
        .task {
            guard let url = url else { return }
            // Загрузка через URLSession
        }
    }
}

Пояснение: В SwiftUI нет встроенного AsyncImage до iOS 15. Этот модификатор работает на iOS 14+.

6. UIKit: анимация перехода между экранами

Промт: "Создай кастомный UIViewControllerAnimatedTransitioning для перехода с эффектом scale и fade."

Пример кода:

class ScaleTransition: NSObject, UIViewControllerAnimatedTransitioning {
    let duration = 0.4

    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return duration
    }

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        guard let toView = transitionContext.view(forKey: .to) else { return }
        toView.transform = CGAffineTransform(scaleX: 0.5, y: 0.5)
        toView.alpha = 0
        transitionContext.containerView.addSubview(toView)

        UIView.animate(withDuration: duration) {
            toView.transform = .identity
            toView.alpha = 1
        } completion: { _ in
            transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
        }
    }
}

Пояснение: Кастомные переходы улучшают UX. Используйте в UINavigationControllerDelegate.

7. Core Data: запрос с фильтрацией через NSPredicate

Промт: "Напиши fetch request для Core Data, который возвращает задачи с датой создания сегодня и статусом 'не выполнено'."

Пример кода:

let request: NSFetchRequest<Task> = Task.fetchRequest()
let calendar = Calendar.current
let startOfDay = calendar.startOfDay(for: Date())
let endOfDay = calendar.date(byAdding: .day, value: 1, to: startOfDay)!
request.predicate = NSPredicate(format: "createdAt >= %@ AND createdAt < %@ AND isDone == NO", startOfDay as NSDate, endOfDay as NSDate)

Пояснение: NSPredicate — мощный инструмент. Избегайте строковых форматов, используйте %@ для безопасности.

8. SwiftUI: EnvironmentObject для темы

Промт: "Реализуй переключение светлой/тёмной темы через EnvironmentObject и @Environment."

Пример кода:

class ThemeManager: ObservableObject {
    @Published var isDarkMode: Bool = false
}

struct ContentView: View {
    @EnvironmentObject var theme: ThemeManager

    var body: some View {
        Text("Привет")
            .preferredColorScheme(theme.isDarkMode ? .dark : .light)
    }
}

Пояснение: EnvironmentObject упрощает передачу данных через иерархию. Не забывайте inject в .environmentObject().

9. Combine: объединение двух Publishers

Промт: "Объедини два Publisher: один для ввода логина, второй для пароля, и создай Publisher для валидации формы."

Пример кода:

let loginPublisher = $login.map { $0.count >= 3 }
let passwordPublisher = $password.map { $0.count >= 6 }
let isFormValid = Publishers.CombineLatest(loginPublisher, passwordPublisher)
    .map { $0 && $1 }
    .eraseToAnyPublisher()

Пояснение: CombineLatest эмитит новое значение каждый раз, когда меняется любой из входных publisher.

10. UIKit: работа с UIScrollView и Keyboard

Промт: "Реализуй автоматический скролл UIScrollView при появлении клавиатуры с использованием NSNotification."

Пример кода:

NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillShowNotification, object: nil, queue: .main) { notification in
    guard let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return }
    scrollView.contentInset.bottom = keyboardFrame.height
    scrollView.verticalScrollIndicatorInsets.bottom = keyboardFrame.height
}

Пояснение: Это базовый паттерн для форм. Не забудьте отписаться от уведомлений в deinit.

11. SwiftUI: GeometryReader для адаптивного UI

Промт: "Используй GeometryReader для создания сетки из квадратных ячеек, ширина которых равна половине ширины экрана."

Пример кода:

GeometryReader { geometry in
    let width = (geometry.size.width - 20) / 2
    LazyVGrid(columns: [GridItem(.fixed(width)), GridItem(.fixed(width))]) {
        ForEach(0..<10) { index in
            Rectangle().frame(width: width, height: width)
        }
    }
}

Пояснение: GeometryReader занимает всё доступное пространство. Используйте с осторожностью, чтобы избежать лишних перерисовок.

12. Core Data: миграция через Mapping Model

Промт: "Создай Mapping Model для Core Data, если изменилось имя атрибута 'name' на 'fullName'."

Пример кода:

// В Mapping Model.xcmappingmodel задайте:
// Source: name, Destination: fullName
// В коде: NSMappingModel(from: [Bundle.main], forSourceModel: sourceModel, destinationModel: destinationModel)

Пояснение: Mapping Model позволяет переименовывать поля без потери данных. Альтернатива — лёгкая миграция (NSInferMappingModelAutomaticallyOption).

13. SwiftUI: кастомный progress bar с анимацией

Промт: "Создай анимированный progress bar с градиентом и закруглёнными краями."

Пример кода:

struct ProgressBar: View {
    @Binding var progress: Double

    var body: some View {
        GeometryReader { geometry in
            ZStack(alignment: .leading) {
                RoundedRectangle(cornerRadius: 8).fill(Color.gray.opacity(0.3))
                RoundedRectangle(cornerRadius: 8)
                    .fill(LinearGradient(gradient: Gradient(colors: [.blue, .purple]), startPoint: .leading, endPoint: .trailing))
                    .frame(width: geometry.size.width * CGFloat(progress))
                    .animation(.easeInOut, value: progress)
            }
        }
        .frame(height: 16)
    }
}

Пояснение: .animation(.easeInOut) плавно анимирует изменение progress. Используйте с @State.

14. Combine: обработка ошибок с catch

Промт: "Обработай ошибку в Combine pipeline с помощью catch и верни запасное значение."

Пример кода:

URLSession.shared.dataTaskPublisher(for: url)
    .tryMap { data, response in
        guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
            throw URLError(.badServerResponse)
        }
        return data
    }
    .catch { error in
        Just(Data())
    }
    .sink(receiveCompletion: { _ in }, receiveValue: { data in
        // обработка
    })

Пояснение: catch заменяет ошибку на fallback publisher. Для логирования используйте handleEvents.

15. UIKit: кастомный UILabel с Insets

Промт: "Создай UILabel с отступами внутри (padding) через UIEdgeInsets."

Пример кода:

class InsetLabel: UILabel {
    var insets = UIEdgeInsets(top: 4, left: 8, bottom: 4, right: 8)

    override func drawText(in rect: CGRect) {
        super.drawText(in: rect.inset(by: insets))
    }

    override var intrinsicContentSize: CGSize {
        let size = super.intrinsicContentSize
        return CGSize(width: size.width + insets.left + insets.right, height: size.height + insets.top + insets.bottom)
    }
}

Пояснение: В UIKit нет встроенного padding для UILabel. Этот класс решает задачу без Auto Layout хаков.

Заключение

Эти 15 промтов покрывают 80% ежедневных задач iOS-разработчика: от настройки Core Data до анимаций в UIKit. Сохраните эту статью как шпаргалку — каждый промт сэкономит вам от 15 минут до часа. Попробуйте адаптировать их под свои проекты: замените мок-данные на реальные, добавьте свои модификаторы или расширьте обработку ошибок.

А если хотите ещё больше готовых решений — следите за обновлениями блога Asibiont. Мы регулярно публикуем подборки промтов для Swift, SwiftUI и UIKit.

Полезные ссылки
- Apple Developer Documentation: Core Data
- Hacking with Swift: SwiftUI
- Ray Wenderlich: Combine Tutorial

← Все статьи

Комментарии

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

Интеграция WordPress с AI-агентом ASI Biont: автоматизация контента, SEO и управления сайтом через чат

16 июля 2026

Inside Ode с Anthropic: как стартап ставит на то, что будущее enterprise за AI-сервисами

16 июля 2026

Стандарты кибербезопасности: ISO 27001, NIST, PCI DSS – ваш карьерный ускоритель в 2026 году

16 июля 2026

Откройте будущее финансов: интеграция AI-агента с DeFi через ASI Biont для автоматизированного фарминга доходности и ребалансировки портфеля

16 июля 2026

High-Bandwidth Flash: как быстрая память меняет хранение весов моделей в эпоху Vibe Coding

16 июля 2026

Welcome Inkling: Как Thinking Machines переопределяет AI-агентов в 2026 году

16 июля 2026

Ускорьте свои кампании myTarget с помощью ИИ без кода: руководство по интеграции с агентом ASI Biont

16 июля 2026

Освоение анализа временных рядов: Почему структурированный курс превосходит самостоятельное обучение с ИИ на ASI Biont

16 июля 2026

Vibe Coding Development Services: Что на самом деле входит в услуги и почему бизнесу в 2026 году они необходимы

16 июля 2026