10 промтов для Swift и iOS: SwiftUI, UIKit, Core Data

Разработка под iOS — это постоянное решение задач: от вёрстки экранов до работы с Core Data и Combine. Даже опытные Swift-разработчики тратят часы на написание шаблонных ViewController'ов, отладку макетов или настройку NSFetchedResultsController. А что, если часть этой работы можно переложить на AI?

Я собрал 10 конкретных промтов, которые помогут ускорить рутину. Каждый промт — это не абстрактный совет, а готовый запрос, который можно скопировать и вставить в ChatGPT или Claude. Внутри — примеры кода, пояснения и ссылки на официальную документацию Apple (Swift.org, developer.apple.com).

1. Генерация SwiftUI View с заданным макетом

Для чего: Быстро получить работающий код экрана на SwiftUI, не отвлекаясь на вспоминание синтаксиса.

Промт:

Напиши SwiftUI View для экрана профиля пользователя. Используй VStack, HStack, AsyncImage для аватара (URL placeholder), TextField для имени, Slider для возраста (от 18 до 100) и кнопку «Сохранить». Все элементы должны иметь отступы 16pt. Не забудь импорт SwiftUI.

Пример использования:

struct ProfileView: View {
    @State private var name: String = ""
    @State private var age: Double = 25

    var body: some View {
        VStack(spacing: 16) {
            AsyncImage(url: URL(string: "https://example.com/avatar.png")) { image in
                image.resizable().frame(width: 80, height: 80).clipShape(Circle())
            } placeholder: {
                ProgressView()
            }
            TextField("Имя", text: $name).textFieldStyle(RoundedBorderTextFieldStyle())
            HStack {
                Text("Возраст: \(Int(age))")
                Slider(value: $age, in: 18...100, step: 1)
            }
            Button("Сохранить") { /* action */ }.buttonStyle(.borderedProminent)
        }.padding(16)
    }
}

Совет: Уточняй параметры — @State, @Binding, @ObservedObject. SwiftUI любит декларативность, и AI часто выдаёт читаемый код, если явно указать модификаторы.

2. Создание UIKit ViewController с Auto Layout

Для чего: Когда проект legacy или нужен более тонкий контроль над layout.

Промт:

Создай UIViewController на Swift с двумя UILabel (заголовок и описание) и UIButton. Используй Auto Layout с NSLayoutConstraint (без storyboard). Заголовок — шрифт Bold 20, описание — System 14 серого цвета, кнопка — синяя с закруглёнными углами. Расположи всё вертикально по центру с отступами 20pt.

Пример использования:

class InfoViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let titleLabel = UILabel()
        titleLabel.text = "Привет!"
        titleLabel.font = .boldSystemFont(ofSize: 20)

        let descLabel = UILabel()
        descLabel.text = "Это описание"
        descLabel.font = .systemFont(ofSize: 14)
        descLabel.textColor = .gray

        let button = UIButton(type: .system)
        button.setTitle("Нажать", for: .normal)
        button.backgroundColor = .systemBlue
        button.layer.cornerRadius = 8

        [titleLabel, descLabel, button].forEach {
            $0.translatesAutoresizingMaskIntoConstraints = false
            view.addSubview($0)
        }

        NSLayoutConstraint.activate([
            titleLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            titleLabel.topAnchor.constraint(equalTo: view.centerYAnchor, constant: -40),
            descLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            descLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 8),
            button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            button.topAnchor.constraint(equalTo: descLabel.bottomAnchor, constant: 20),
            button.widthAnchor.constraint(equalToConstant: 120),
            button.heightAnchor.constraint(equalToConstant: 44)
        ])
    }
}

Совет: Если нужно больше элементов — опиши их в промте. AI хорошо понимает иерархию, если дать чёткие указания по leading/trailing/top/bottom.

3. Core Data: модель и CRUD-операции

Для чего: Сгенерировать код для работы с локальной базой данных, не заглядывая в документацию каждый раз.

Промт:

Напиши код для Core Data модели «Задача» (Task) с атрибутами: id (UUID), title (String), isCompleted (Bool), createdAt (Date). Создай функцию для добавления задачи и выборки всех задач, отсортированных по createdAt по убыванию. Контекст передавай через параметр.

Пример использования:

import CoreData

@objc(Task)
public class Task: NSManagedObject {
    @NSManaged public var id: UUID
    @NSManaged public var title: String
    @NSManaged public var isCompleted: Bool
    @NSManaged public var createdAt: Date
}

func addTask(title: String, context: NSManagedObjectContext) {
    let task = Task(context: context)
    task.id = UUID()
    task.title = title
    task.isCompleted = false
    task.createdAt = Date()
    try? context.save()
}

func fetchAllTasks(context: NSManagedObjectContext) -> [Task] {
    let request = NSFetchRequest<Task>(entityName: "Task")
    request.sortDescriptors = [NSSortDescriptor(key: "createdAt", ascending: false)]
    return (try? context.fetch(request)) ?? []
}

Совет: В промте уточни, нужен ли @objc и @NSManaged. Для нового Core Data (iOS 13+) можно использовать NSManagedObject с @FetchRequest в SwiftUI, но если проект старый — лучше явно указать.

4. Настройка NSFetchedResultsController для UIKit

Для чего: Связать Core Data с UITableView и автоматически обновлять данные при изменениях.

Промт:

Напиши класс-контроллер (UIViewController) с UITableView и NSFetchedResultsController для сущности Task (атрибуты: title, isCompleted, createdAt). Секции по isCompleted, внутри — сортировка по createdAt. Реализуй делегат NSFetchedResultsControllerDelegate для автоматического обновления таблицы.

Пример использования (фрагмент):

class TasksViewController: UIViewController, NSFetchedResultsControllerDelegate {
    private let tableView = UITableView()
    private var fetchedResultsController: NSFetchedResultsController<Task>!

    override func viewDidLoad() {
        super.viewDidLoad()
        setupFetchedResultsController()
        tableView.dataSource = self
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
    }

    private func setupFetchedResultsController() {
        let request = Task.fetchRequest()
        request.sortDescriptors = [
            NSSortDescriptor(key: "isCompleted", ascending: true),
            NSSortDescriptor(key: "createdAt", ascending: false)
        ]
        fetchedResultsController = NSFetchedResultsController(
            fetchRequest: request,
            managedObjectContext: CoreDataStack.shared.context,
            sectionNameKeyPath: "isCompleted",
            cacheName: nil
        )
        fetchedResultsController.delegate = self
        try? fetchedResultsController.performFetch()
    }

    func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
        tableView.beginUpdates()
    }
    func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
        tableView.endUpdates()
    }
}

Совет: Укажи, нужен ли cacheName. Если данные часто меняются — лучше nil, чтобы избежать устаревшего кэша.

5. Combine: подписка на Publisher и отмена

Для чего: Быстро написать код реактивного обновления UI при изменении данных.

Промт:

Напиши Swift код с использованием Combine: создай PassthroughSubject<String, Never>, подпишись на него с помощью sink и выведи значение в print. Сохрани AnyCancellable в свойство. Также добавь пример с map, который преобразует строку в верхний регистр.

Пример использования:

import Combine

var cancellables = Set<AnyCancellable>()

let subject = PassthroughSubject<String, Never>()

subject
    .map { $0.uppercased() }
    .sink { value in
        print("Получено: \(value)")
    }
    .store(in: &cancellables)

subject.send("hello") // напечатает: Получено: HELLO
subject.send("world") // напечатает: Получено: WORLD

Совет: Добавь в промт @Published для свойств модели. Тогда AI сгенерирует связку с ObservableObject, что удобно в SwiftUI.

6. SwiftUI + Combine: ViewModel с @Published

Для чего: Реактивное обновление SwiftUI View при изменении данных.

Промт:

Создай ObservableObject класс UserViewModel с @Published свойствами: name (String), age (Int). Добавь метод updateUser, который через Combine.Future симулирует загрузку данных с задержкой 1 секунду. В SwiftUI ContentView используй @StateObject и отобрази name и age. Пока данные загружаются  покажи ProgressView.

Пример использования (фрагмент):

class UserViewModel: ObservableObject {
    @Published var name = ""
    @Published var age = 0
    @Published var isLoading = false

    func loadUser() {
        isLoading = true
        Future<(String, Int), Never> { promise in
            DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                promise(.success(("Анна", 30)))
            }
        }
        .receive(on: DispatchQueue.main)
        .sink { [weak self] (name, age) in
            self?.name = name
            self?.age = age
            self?.isLoading = false
        }
        .store(in: &cancellables)
    }
}

struct ContentView: View {
    @StateObject private var viewModel = UserViewModel()

    var body: some View {
        if viewModel.isLoading {
            ProgressView()
        } else {
            VStack {
                Text(viewModel.name)
                Text("\(viewModel.age) лет")
            }
        }
    }
}

Совет: В SwiftUI лучше использовать @StateObject для создания и @ObservedObject для передачи.

7. Генерация тестов (XCTest) для модели

Для чего: Не писать boilerplate для Unit-тестов вручную.

Промт:

Напиши XCTestCase для модели User с полями name (String) и age (Int). Тесты: testUserInitialization, testUserAgeValidation (возраст должен быть от 0 до 150). Используй XCTAssertEqual и XCTAssertTrue.

Пример использования:

import XCTest
@testable import MyApp

class UserTests: XCTestCase {
    func testUserInitialization() {
        let user = User(name: "Иван", age: 25)
        XCTAssertEqual(user.name, "Иван")
        XCTAssertEqual(user.age, 25)
    }

    func testUserAgeValidation() {
        let user1 = User(name: "Test", age: 0)
        let user2 = User(name: "Test", age: 150)
        let user3 = User(name: "Test", age: 200)
        XCTAssertTrue(user1.isValidAge)
        XCTAssertTrue(user2.isValidAge)
        XCTAssertFalse(user3.isValidAge)
    }
}

Совет: Укажи в промте, нужны ли mock-объекты. Для Core Data удобно добавить inMemoryPersistentContainer.

8. Создание кастомного модификатора SwiftUI

Для чего: Переиспользовать стили кнопок, текста или вьюх без дублирования кода.

Промт:

Напиши кастомный ViewModifier под названием CardStyle: белый фон, тень (color: .black.opacity(0.1), radius: 8, x: 0, y: 4), скруглённые углы 12pt. Примени его к VStack в ContentView. Также создай extension View с методом .cardStyle().

Пример использования:

struct CardStyle: ViewModifier {
    func body(content: Content) -> some View {
        content
            .background(Color.white)
            .cornerRadius(12)
            .shadow(color: .black.opacity(0.1), radius: 8, x: 0, y: 4)
    }
}

extension View {
    func cardStyle() -> some View {
        modifier(CardStyle())
    }
}

struct ContentView: View {
    var body: some View {
        VStack {
            Text("Карточка")
        }
        .cardStyle()
        .padding()
    }
}

Совет: Если нужны параметры (например, цвет тени), добавь их в промт — AI создаст инициализатор.

9. Работа с URLSession и Codable

Для чего: Быстро получить код для сетевого запроса с парсингом JSON.

Промт:

Напиши класс NetworkService с функцией fetchUsers(completion: @escaping ([User]?, Error?) -> Void). Используй URLSession, Codable. Модель User: id (Int), name (String), email (String). URL: https://jsonplaceholder.typicode.com/users. Обработай ошибки и главный поток.

Пример использования:

struct User: Codable {
    let id: Int
    let name: String
    let email: String
}

class NetworkService {
    func fetchUsers(completion: @escaping ([User]?, Error?) -> Void) {
        guard let url = URL(string: "https://jsonplaceholder.typicode.com/users") else { return }
        URLSession.shared.dataTask(with: url) { data, _, error in
            if let error = error {
                DispatchQueue.main.async { completion(nil, error) }
                return
            }
            guard let data = data else { return }
            do {
                let users = try JSONDecoder().decode([User].self, from: data)
                DispatchQueue.main.async { completion(users, nil) }
            } catch {
                DispatchQueue.main.async { completion(nil, error) }
            }
        }.resume()
    }
}

Совет: Для Swift 5.5+ добавь в промт async/await. Тогда AI сгенерирует функцию с throws и await.

10. SwiftUI анимации: переходы и анимация состояний

Для чего: Быстро добавить плавные переходы между экранами или элементами.

Промт:

Напиши SwiftUI View с кнопкой, которая переключает @State isExpanded. При isExpanded = true покажи Rectangle с анимацией scaleEffect и opacity. Используй withAnimation(.easeInOut(duration: 0.5)). Добавь также transition .slide для появления текста.

Пример использования:

struct AnimatedView: View {
    @State private var isExpanded = false

    var body: some View {
        VStack {
            Button("Анимировать") {
                withAnimation(.easeInOut(duration: 0.5)) {
                    isExpanded.toggle()
                }
            }
            if isExpanded {
                Rectangle()
                    .fill(Color.blue)
                    .frame(width: 100, height: 100)
                    .scaleEffect(isExpanded ? 1.0 : 0.5)
                    .opacity(isExpanded ? 1.0 : 0.0)
                Text("Появился")
                    .transition(.slide)
            }
        }
    }
}

Совет: Для сложных анимаций укажи matchedGeometryEffect — AI может сгенерировать код с героем-анимацией.

Заключение

Эти 10 промтов покрывают большую часть повседневных задач iOS-разработчика: от вёрстки и layout до работы с Core Data, Combine и анимациями. Скопируй подходящий запрос, вставь в AI-помощник и получи готовый код за секунды. Главное — уточняй детали: имена переменных, типы, версии iOS. И не забывай проверять сгенерированный код на соответствие гайдлайнам Apple (Human Interface Guidelines и Swift API Design Guidelines).

Попробуй прямо сейчас: выбери одну задачу из списка, скопируй промт и сгенерируй код. Уверен, ты сэкономишь не один час.

← Все статьи

Комментарии

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