15 промтов для Swift и iOS: SwiftUI, UIKit, Core Data — подборка 2026
Разработка под iOS — это постоянный поиск баланса между производительностью, читаемостью кода и временем на реализацию. С появлением больших языковых моделей многие разработчики начали использовать промты (подсказки для генерации кода) как инструмент для ускорения рутины. Но не все промты одинаково полезны: одни генерируют шаблонный код, который всё равно приходится переписывать, другие — действительно экономят часы.
В этой статье я собрал 15 проверенных промтов для Swift и iOS, которые покрывают три ключевые области: SwiftUI (современный декларативный интерфейс), UIKit (классический фреймворк для сложных UI) и Core Data (работа с локальными данными). Каждый промт сопровождается реальным примером, пояснением и кодом. Вы сможете скопировать его и сразу применить в своём проекте.
Базовые промты (уровень 1–3)
1. Генерация модели данных для SwiftUI
Задача: Создать структуру данных для списка задач с Codable и поддержкой SwiftUI.
Промт:
Напиши структуру TaskItem с полями id (UUID), title (String), isCompleted (Bool), dueDate (Date?). Реализуй Codable, Identifiable и Hashable. Добавь пример инициализации и загрузки из JSON.
Пример результата:
import Foundation
struct TaskItem: Identifiable, Codable, Hashable {
let id: UUID
var title: String
var isCompleted: Bool
var dueDate: Date?
init(id: UUID = UUID(), title: String, isCompleted: Bool = false, dueDate: Date? = nil) {
self.id = id
self.title = title
self.isCompleted = isCompleted
self.dueDate = dueDate
}
}
// Пример загрузки из JSON
let jsonData = """
{
"id": "E621E1F8-C36C-495A-93FC-0C247A3E6E5F",
"title": "Купить продукты",
"isCompleted": false,
"dueDate": "2026-07-30T12:00:00Z"
}
""".data(using: .utf8)!
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
if let task = try? decoder.decode(TaskItem.self, from: jsonData) {
print(task.title) // "Купить продукты"
}
Пояснение: Промт задаёт конкретную структуру с протоколами, что избавляет от необходимости писать boilerplate. В результате получаем готовую модель, которую можно сразу использовать в SwiftUI-вьюхах (благодаря Identifiable) и передавать через NavigationLink или List.
2. Создание простого экрана логина на SwiftUI
Задача: Экран входа с полями email/password и кнопкой.
Промт:
Создай LoginView на SwiftUI с State для email и password, кнопкой "Войти", обработкой ошибок (показывать алерт если поля пустые). Используй @State и VStack. Минимальная стилизация.
Пример результата:
import SwiftUI
struct LoginView: View {
@State private var email = ""
@State private var password = ""
@State private var showAlert = false
@State private var alertMessage = ""
var body: some View {
VStack(spacing: 16) {
TextField("Email", text: $email)
.textFieldStyle(.roundedBorder)
.keyboardType(.emailAddress)
.autocapitalization(.none)
SecureField("Пароль", text: $password)
.textFieldStyle(.roundedBorder)
Button("Войти") {
if email.isEmpty || password.isEmpty {
alertMessage = "Заполните все поля"
showAlert = true
} else {
// Логика входа
print("Вход с \(email)")
}
}
.buttonStyle(.borderedProminent)
}
.padding()
.alert("Ошибка", isPresented: $showAlert) {
Button("OK", role: .cancel) { }
} message: {
Text(alertMessage)
}
}
}
Пояснение: Промт создаёт рабочий экран с валидацией. Это типовой кейс для любого приложения — готовый блок можно вставить в проект и доработать под свои нужды.
3. UITableView с кастомной ячейкой на UIKit
Задача: Таблица с кастомными ячейками и данными из массива.
Промт:
Создай UIViewController с UITableView. Используй кастомную ячейку CustomCell (с label и imageView). Данные — массив строк. Реализуй методы dataSource и delegate. Настрой Auto Layout в ячейке.
Пример результата:
import UIKit
class CustomCell: UITableViewCell {
static let identifier = "CustomCell"
let titleLabel = UILabel()
let iconImageView = UIImageView()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupViews()
}
required init?(coder: NSCoder) { fatalError() }
private func setupViews() {
iconImageView.translatesAutoresizingMaskIntoConstraints = false
titleLabel.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(iconImageView)
contentView.addSubview(titleLabel)
NSLayoutConstraint.activate([
iconImageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16),
iconImageView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor),
iconImageView.widthAnchor.constraint(equalToConstant: 40),
iconImageView.heightAnchor.constraint(equalToConstant: 40),
titleLabel.leadingAnchor.constraint(equalTo: iconImageView.trailingAnchor, constant: 12),
titleLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -16),
titleLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor)
])
}
}
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
let tableView = UITableView()
let items = ["Первый", "Второй", "Третий"]
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(tableView)
tableView.frame = view.bounds
tableView.dataSource = self
tableView.delegate = self
tableView.register(CustomCell.self, forCellReuseIdentifier: CustomCell.identifier)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { items.count }
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: CustomCell.identifier, for: indexPath) as! CustomCell
cell.titleLabel.text = items[indexPath.row]
cell.iconImageView.image = UIImage(systemName: "star")
return cell
}
}
Пояснение: Промт решает задачу создания таблицы с нуля — от регистрации ячейки до делегата. Экономит время на типовом коде, который обычно пишут в начале проекта.
4. Сохранение и чтение из UserDefaults
Задача: Сохранить настройки приложения.
Промт:
Напиши класс UserSettings для сохранения имени пользователя и тёмной темы в UserDefaults. Используй @Published для SwiftUI совместимости. Добавь методы save и load.
Пример результата:
import Foundation
import Combine
class UserSettings: ObservableObject {
@Published var username: String {
didSet { save() }
}
@Published var isDarkMode: Bool {
didSet { save() }
}
init() {
self.username = UserDefaults.standard.string(forKey: "username") ?? ""
self.isDarkMode = UserDefaults.standard.bool(forKey: "isDarkMode")
}
private func save() {
UserDefaults.standard.set(username, forKey: "username")
UserDefaults.standard.set(isDarkMode, forKey: "isDarkMode")
}
}
Пояснение: Промт создаёт обёртку над UserDefaults с автоматическим сохранением. ObservableObject позволяет использовать класс в SwiftUI через @StateObject.
Продвинутые промты (уровень 4–6)
5. Кастомный модификатор для SwiftUI
Задача: Создать модификатор для кнопки с тенью и скруглением.
Промт:
Создай кастомный ViewModifier под названием PrimaryButtonStyle: background цвет (синий), белый текст, скругление 12, тень (color: .black.opacity(0.2), radius: 4, offset: (0, 2)). Примени к Button.
Пример результата:
import SwiftUI
struct PrimaryButtonStyle: ViewModifier {
func body(content: Content) -> some View {
content
.padding(.horizontal, 24)
.padding(.vertical, 12)
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(12)
.shadow(color: .black.opacity(0.2), radius: 4, x: 0, y: 2)
}
}
extension View {
func primaryButtonStyle() -> some View {
self.modifier(PrimaryButtonStyle())
}
}
Пояснение: Модификаторы — основа SwiftUI. Этот промт учит создавать переиспользуемые стили, что улучшает поддерживаемость кода.
6. Работа с Core Data: создание и запрос
Задача: Сохранение и извлечение сущности Person.
Промт:
Создай Core Data стек (NSPersistentContainer) для модели Person (name: String, age: Int16). Напиши функцию savePerson и fetchPersons. Используй @FetchRequest в SwiftUI.
Пример результата:
import CoreData
import SwiftUI
struct PersistenceController {
static let shared = PersistenceController()
let container: NSPersistentContainer
init() {
container = NSPersistentContainer(name: "Model")
container.loadPersistentStores { _, error in
if let error = error { fatalError(error.localizedDescription) }
}
}
func savePerson(name: String, age: Int16) {
let context = container.viewContext
let person = Person(context: context)
person.name = name
person.age = age
try? context.save()
}
func fetchPersons() -> [Person] {
let request: NSFetchRequest<Person> = Person.fetchRequest()
return (try? container.viewContext.fetch(request)) ?? []
}
}
// Использование в SwiftUI
struct ContentView: View {
@FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \Person.name, ascending: true)])
private var persons: FetchedResults<Person>
var body: some View {
List(persons, id: \.self) { person in
Text("\(person.name ?? ""), \(person.age)")
}
}
}
Пояснение: Промт показывает полный цикл Core Data: настройка стека, запись, чтение и интеграция со SwiftUI. Подходит для приложений с локальными данными.
7. Combine: подписка на Notification
Задача: Реагировать на уведомление о смене клавиатуры.
Промт:
Напиши Combine-паблишер для keyboardWillShowNotification. При получении уведомления выведи высоту клавиатуры в консоль. Используй sink и cancellable.
Пример результата:
import Combine
import UIKit
class KeyboardObserver: ObservableObject {
@Published var keyboardHeight: CGFloat = 0
private var cancellable: AnyCancellable?
init() {
cancellable = NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)
.map { notification -> CGFloat in
(notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect)?.height ?? 0
}
.sink { [weak self] height in
self?.keyboardHeight = height
print("Высота клавиатуры: \(height)")
}
}
deinit { cancellable?.cancel() }
}
Пояснение: Промт объединяет Combine и UIKit — полезно для адаптивного интерфейса при появлении клавиатуры.
8. Async/await для сетевых запросов
Задача: Загрузка данных из API с URLSession.
Промт:
Напиши функцию для загрузки списка пользователей с https://jsonplaceholder.typicode.com/users. Используй async/await, Codable модель User. Обработай ошибки.
Пример результата:
import Foundation
struct User: Codable, Identifiable {
let id: Int
let name: String
let email: String
}
enum NetworkError: Error {
case badURL
case decodingError
}
func fetchUsers() async throws -> [User] {
guard let url = URL(string: "https://jsonplaceholder.typicode.com/users") else {
throw NetworkError.badURL
}
let (data, _) = try await URLSession.shared.data(from: url)
guard let users = try? JSONDecoder().decode([User].self, from: data) else {
throw NetworkError.decodingError
}
return users
}
// Использование
Task {
do {
let users = try await fetchUsers()
print(users.count) // 10
} catch {
print("Ошибка: \(error)")
}
}
Пояснение: Промт использует современный async/await — это стандарт для сетевых запросов в iOS 15+. Подходит для любого приложения с API.
Экспертные промты (уровень 7–9)
9. DI-контейнер на Swift
Задача: Простой контейнер внедрения зависимостей.
Промт:
Создай DIContainer с регистрацией сервисов по протоколам. Реализуй register<T>(_:) и resolve<T>(). Используй словарь и type erasure.
Пример результата:
import Foundation
protocol Service { }
class DIContainer {
static let shared = DIContainer()
private var services: [String: Any] = [:]
func register<T>(_ type: T.Type, service: T) {
let key = String(describing: type)
services[key] = service
}
func resolve<T>(_ type: T.Type) -> T? {
let key = String(describing: type)
return services[key] as? T
}
}
// Пример использования
class UserService: Service { }
DIContainer.shared.register(UserService.self, service: UserService())
let service: UserService? = DIContainer.shared.resolve(UserService.self)
Пояснение: DI-контейнер упрощает тестирование и замену зависимостей. Промт даёт минимальную реализацию, которую можно расширить.
10. Пагинация в SwiftUI
Задача: Бесконечный список с подгрузкой при скролле.
Промт:
Создай PaginatedListView: по мере скролла загружай следующую страницу. Используй async/await, показывай индикатор загрузки в конце списка. Модель — Post (id, title).
Пример результата:
import SwiftUI
struct Post: Codable, Identifiable {
let id: Int
let title: String
}
class PaginatedViewModel: ObservableObject {
@Published var posts: [Post] = []
@Published var isLoading = false
private var currentPage = 1
func loadMore() {
guard !isLoading else { return }
isLoading = true
Task {
let newPosts = await fetchPosts(page: currentPage)
await MainActor.run {
posts.append(contentsOf: newPosts)
currentPage += 1
isLoading = false
}
}
}
private func fetchPosts(page: Int) async -> [Post] {
guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts?_page=\(page)&_limit=10") else { return [] }
guard let (data, _) = try? await URLSession.shared.data(from: url) else { return [] }
return (try? JSONDecoder().decode([Post].self, from: data)) ?? []
}
}
struct PaginatedListView: View {
@StateObject private var viewModel = PaginatedViewModel()
var body: some View {
List {
ForEach(viewModel.posts) { post in
Text(post.title)
}
if viewModel.isLoading {
ProgressView()
.frame(maxWidth: .infinity)
}
}
.onAppear { viewModel.loadMore() }
.onScrollToBottom { viewModel.loadMore() }
}
}
Пояснение: Промт реализует бесконечный скролл — критично для лент новостей или каталогов.
11. Core Data с миграцией
Задача: Добавить новое поле в модель без потери данных.
Промт:
Опиши шаги для лёгкой миграции Core Data: добавление поля phone (String) к сущности Person. Укажи настройки в NSPersistentContainer: shouldAddStoreAsynchronously, shouldMigrateStoreAutomatically.
Пример результата:
import CoreData
let container = NSPersistentContainer(name: "Model")
container.persistentStoreDescriptions.first?.shouldMigrateStoreAutomatically = true
container.persistentStoreDescriptions.first?.shouldAddStoreAsynchronously = true
container.loadPersistentStores { _, error in
if let error = error { print(error) }
}
Пояснение: Промт решает проблему обновления модели в продакшене — автоматическая миграция предотвращает краши.
12. Сложная анимация в SwiftUI
Задача: Анимация перехода между двумя состояниями.
Промт:
Создай анимацию: при нажатии кнопки квадрат меняет цвет (синий/красный) и поворачивается на 360 градусов. Используй withAnimation(.easeInOut(duration: 1)).
Пример результата:
import SwiftUI
struct AnimationView: View {
@State private var isToggled = false
var body: some View {
VStack {
Rectangle()
.fill(isToggled ? Color.red : Color.blue)
.frame(width: 100, height: 100)
.rotationEffect(.degrees(isToggled ? 360 : 0))
.animation(.easeInOut(duration: 1), value: isToggled)
Button("Toggle") {
withAnimation {
isToggled.toggle()
}
}
}
}
}
Пояснение: Промт демонстрирует базовую анимацию свойств — основа для более сложных визуальных эффектов.
13. Обработка ошибок в SwiftUI
Задача: Показать алерт при сетевой ошибке.
Промт:
Создай ErrorHandlingViewModel с @Published errorMessage. При ошибке загрузки покажи алерт. Используй enum ErrorType.
Пример результата:
import SwiftUI
enum AppError: LocalizedError {
case network
case decoding
var errorDescription: String? {
switch self {
case .network: return "Нет соединения"
case .decoding: return "Ошибка данных"
}
}
}
class ErrorHandlingViewModel: ObservableObject {
@Published var showError = false
@Published var error: AppError?
func loadData() {
Task {
do {
// имитация ошибки
throw AppError.network
} catch let error as AppError {
await MainActor.run {
self.error = error
self.showError = true
}
}
}
}
}
Пояснение: Промт учит централизованной обработке ошибок — улучшает UX и отладку.
14. SwiftUI и UIKit вместе
Задача: Встроить UIView (WKWebView) в SwiftUI.
Промт:
Создай UIViewRepresentable для WKWebView, загружающий URL. Используй в SwiftUI через WebView(url:).
Пример результата:
import SwiftUI
import WebKit
struct WebView: UIViewRepresentable {
let url: URL
func makeUIView(context: Context) -> WKWebView {
let webView = WKWebView()
webView.load(URLRequest(url: url))
return webView
}
func updateUIView(_ uiView: WKWebView, context: Context) { }
}
struct ContentView: View {
var body: some View {
WebView(url: URL(string: "https://asibiont.com")!)
}
}
Пояснение: Промт решает задачу интеграции UIKit-компонентов в SwiftUI — полезно для карт, веб-вью и кастомных элементов.
15. Unit-тесты для модели
Задача: Написать тесты для TaskItem.
Промт:
Напиши XCTestCase для TaskItem: проверка инициализации, кодирования/декодирования, Hashable. Используй XCTest.
Пример результата:
import XCTest
@testable import YourApp
class TaskItemTests: XCTestCase {
func testInit() {
let task = TaskItem(title: "Test")
XCTAssertEqual(task.title, "Test")
XCTAssertFalse(task.isCompleted)
}
func testEncodingDecoding() throws {
let task = TaskItem(title: "Test")
let data = try JSONEncoder().encode(task)
let decoded = try JSONDecoder().decode(TaskItem.self, from: data)
XCTAssertEqual(task.id, decoded.id)
}
func testHashable() {
let task1 = TaskItem(title: "A")
let task2 = TaskItem(title: "A")
XCTAssertNotEqual(task1, task2) // разные id
}
}
Пояснение: Промт показывает, как автоматизировать тестирование моделей — основа для CI/CD.
Заключение
Эти 15 промтов покрывают большинство повседневных задач iOS-разработчика: от создания моделей до сложной анимации и тестирования. Главное — не копировать их слепо, а адаптировать под свой проект. Я рекомендую сохранить эту подборку и возвращаться к ней при старте нового модуля.
Если вы хотите глубже изучить Swift, SwiftUI или Core Data, обратите внимание на официальную документацию Apple (developer.apple.com) — это лучший источник проверенной информации. А промты останутся вашим помощником для быстрого прототипирования.
Попробуйте применить любой из промтов прямо сейчас — и вы увидите, как ускоряется разработка.
Комментарии