10 Prompts for Swift and iOS Development: SwiftUI, UIKit, Core Data, and Combine

Introduction

Building modern iOS applications in 2026 requires mastering multiple frameworks: SwiftUI for declarative interfaces, UIKit for complex custom layouts, Core Data for persistent storage, and Combine for reactive streams. As an iOS developer, you spend hours writing boilerplate, debugging state management, and optimizing performance. What if you could generate production-quality code, test scenarios, and architecture outlines in seconds? This article delivers 10 ready-to-use prompts for Swift and iOS development that help you accelerate your workflow with AI tools. Each prompt is specific, copy-paste ready, and includes a usage example so you can apply it immediately.

Whether you're a junior developer learning SwiftUI or a senior engineer refactoring a UIKit project, these prompts will save you time and reduce cognitive load. Let's dive into the practical prompts.

1. SwiftUI View Generation with State Management

Task: Generate a SwiftUI view with proper @State, @Binding, and @ObservedObject usage.

Prompt:

Generate a SwiftUI view for a todo list app. Include:
- A @State private var for a text field input
- A @ObservedObject for a TodoStore class conforming to ObservableObject
- A List with ForEach that displays items and allows deletion on swipe
- A TextField and Button to add new items
- Use iOS 18 style with .listStyle(.insetGrouped)
Provide the full code for both the view and the TodoStore model.

Usage Example:
Paste this prompt into an AI coding assistant (e.g., ChatGPT, Claude). The output will be a complete SwiftUI view like:

class TodoStore: ObservableObject {
    @Published var items: [String] = []
}

struct TodoListView: View {
    @State private var newItem = ""
    @ObservedObject var store = TodoStore()

    var body: some View {
        NavigationStack {
            List {
                ForEach(store.items, id: \.self) { item in
                    Text(item)
                }
                .onDelete { indexSet in
                    store.items.remove(atOffsets: indexSet)
                }
            }
            .listStyle(.insetGrouped)
            .navigationTitle("Todos")
            .toolbar {
                ToolbarItem(placement: .bottomBar) {
                    HStack {
                        TextField("New item", text: $newItem)
                        Button("Add") {
                            guard !newItem.isEmpty else { return }
                            store.items.append(newItem)
                            newItem = ""
                        }
                    }
                }
            }
        }
    }
}

2. UIKit View Controller with Auto Layout and Delegate Pattern

Task: Create a UIKit view controller with programmatic Auto Layout and a custom delegate.

Prompt:

Generate a UIKit UIViewController that contains a UITextField, a UIButton, and a UILabel. Use Auto Layout constraints in code (no storyboards). The button should validate that the text field is not empty and call a delegate method. Define a protocol named FormViewDelegate with a method didSubmit(text: String). Provide the full view controller code and a sample parent view controller that conforms to the delegate.

Usage Example:
This prompt produces a reusable form component. The delegate pattern allows the parent to handle submission. Example output includes:

protocol FormViewDelegate: AnyObject {
    func didSubmit(text: String)
}

class FormViewController: UIViewController {
    weak var delegate: FormViewDelegate?
    private let textField = UITextField()
    private let submitButton = UIButton(type: .system)
    private let statusLabel = UILabel()

    override func viewDidLoad() {
        super.viewDidLoad()
        setupViews()
        setupConstraints()
    }

    private func setupViews() {
        textField.borderStyle = .roundedRect
        textField.placeholder = "Enter text"
        submitButton.setTitle("Submit", for: .normal)
        submitButton.addTarget(self, action: #selector(submitTapped), for: .touchUpInside)
        statusLabel.text = "Waiting for input"
        statusLabel.textAlignment = .center
        [textField, submitButton, statusLabel].forEach { $0.translatesAutoresizingMaskIntoConstraints = false; view.addSubview($0) }
    }

    private func setupConstraints() {
        NSLayoutConstraint.activate([
            textField.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            textField.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 40),
            textField.widthAnchor.constraint(equalToConstant: 250),
            submitButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            submitButton.topAnchor.constraint(equalTo: textField.bottomAnchor, constant: 20),
            statusLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            statusLabel.topAnchor.constraint(equalTo: submitButton.bottomAnchor, constant: 20)
        ])
    }

    @objc private func submitTapped() {
        guard let text = textField.text, !text.isEmpty else {
            statusLabel.text = "Please enter text"
            statusLabel.textColor = .red
            return
        }
        delegate?.didSubmit(text: text)
        statusLabel.text = "Submitted: \(text)"
        statusLabel.textColor = .green
    }
}

3. Core Data Model Setup with Fetch Request

Task: Define a Core Data model and write a fetch request with sorting and predicate.

Prompt:

Generate a Core Data model for a Book entity with attributes: title (String), author (String), publicationDate (Date), and pages (Int32). Then write a function that fetches all books published after a given date, sorted by publicationDate descending. Use NSFetchRequest and NSSortDescriptor. Assume the context is passed as a parameter. Provide the complete function signature and implementation.

Usage Example:
The prompt yields:

func fetchRecentBooks(after date: Date, in context: NSManagedObjectContext) -> [Book] {
    let request: NSFetchRequest<Book> = Book.fetchRequest()
    request.predicate = NSPredicate(format: "publicationDate > %@", date as NSDate)
    request.sortDescriptors = [NSSortDescriptor(key: "publicationDate", ascending: false)]
    do {
        return try context.fetch(request)
    } catch {
        print("Fetch failed: \(error.localizedDescription)")
        return []
    }
}

4. Combine Publisher and Subscriber for Networking

Task: Create a Combine pipeline that fetches JSON from a URL and decodes it.

Prompt:

Write a Combine-based networking function that:
- Uses URLSession.dataTaskPublisher
- Maps the response to a Codable struct (e.g., User: Decodable)
- Uses decode(type:decoder:) with JSONDecoder
- Receives on DispatchQueue.main
- Handles errors with replaceError(with:) or sink's completion
Return an AnyCancellable? from the function.

Usage Example:

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

func fetchUser(url: URL) -> AnyCancellable? {
    return URLSession.shared.dataTaskPublisher(for: url)
        .map(\.data)
        .decode(type: User.self, decoder: JSONDecoder())
        .receive(on: DispatchQueue.main)
        .sink(receiveCompletion: { completion in
            if case .failure(let error) = completion {
                print("Error: \(error.localizedDescription)")
            }
        }, receiveValue: { user in
            print("User: \(user.name)")
        })
}

5. SwiftUI Navigation with Coordinator Pattern

Task: Implement a SwiftUI navigation system using a coordinator (ObservableObject) that manages push and modal transitions.

Prompt:

Create a SwiftUI navigation coordinator using an ObservableObject class. It should have a @Published path array for NavigationStack and a @Published var for presenting a sheet. Include methods: push(_ view: AnyHashable), pop(), popToRoot(), and presentSheet(_ view: AnyHashable). Then show a sample ContentView that uses the coordinator with two screens: HomeView and DetailView. Use iOS 18 NavigationStack.

Usage Example:
The coordinator pattern keeps navigation logic separate from views, making testing easier. Example output includes a NavigationStack with a path binding.

6. Unit Tests for a ViewModel

Task: Write XCTest unit tests for a SwiftUI ViewModel that performs validation.

Prompt:

Write XCTest unit tests for a LoginViewModel class that has:
- @Published var email: String
- @Published var password: String
- @Published var isButtonEnabled: Bool (true if email is valid and password length >= 6)
- func login() -> Bool (simulates API call, returns true if email contains "@")
Tests should cover: initial state, valid email/password enables button, invalid email disables, login success/failure.

Usage Example:

class LoginViewModelTests: XCTestCase {
    func testButtonDisabledWhenEmailInvalid() {
        let vm = LoginViewModel()
        vm.email = "test"
        vm.password = "123456"
        XCTAssertFalse(vm.isButtonEnabled)
    }
}

7. Performance Optimization with Instruments

Task: Identify and fix common performance issues in a SwiftUI list.

Prompt:

Explain three common performance pitfalls in SwiftUI LazyVStack or List and how to fix them. Include code examples for each: (1) unnecessary re-renders due to missing Equatable conformance, (2) using LazyVStack inside a ScrollView without proper identity, (3) heavy computation in the body. Provide before/after snippets.

Usage Example:
This prompt helps you write efficient lists. The AI explains using .equatable() modifier, ensuring stable IDs, and moving heavy work to background queues.

8. Core Data Migration Strategy

Task: Generate a lightweight migration setup for a Core Data model change.

Prompt:

I have a Core Data model with an Entity "Person" with attributes name (String) and age (Int16). I want to add a new optional attribute email (String). Write the steps to enable lightweight migration in the NSPersistentContainer, and show the updated container setup code. Also explain how to create a mapping model if lightweight migration is insufficient.

Usage Example:

let container = NSPersistentContainer(name: "Model")
container.persistentStoreDescriptions.first?.shouldMigrateStoreAutomatically = true
container.persistentStoreDescriptions.first?.shouldInferMappingModelAutomatically = true
container.loadPersistentStores { _, error in
    if let error = error { print(error.localizedDescription) }
}

9. Integrating UIKit into SwiftUI with UIViewRepresentable

Task: Wrap a UIKit component (e.g., UIPickerView) for use in SwiftUI.

Prompt:

Create a SwiftUI wrapper for UIPickerView using UIViewRepresentable. The wrapper should accept a @Binding<Int> for the selected row and an array of strings as data. Implement makeUIView, updateUIView, and a Coordinator that acts as UIPickerViewDelegate and UIPickerViewDataSource. Provide the complete code and a sample usage in a SwiftUI view.

Usage Example:

struct PickerView: UIViewRepresentable {
    @Binding var selection: Int
    let data: [String]

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    func makeUIView(context: Context) -> UIPickerView {
        let picker = UIPickerView()
        picker.dataSource = context.coordinator
        picker.delegate = context.coordinator
        return picker
    }

    func updateUIView(_ uiView: UIPickerView, context: Context) {
        uiView.selectRow(selection, inComponent: 0, animated: false)
    }
}

10. Error Handling in Combine Chains

Task: Implement robust error handling with retry logic in a Combine pipeline.

Prompt:

Write a Combine pipeline that fetches data from a URL, retries up to 3 times with a 2-second delay between attempts, and if all retries fail, returns a default value. Use .retry() and .catch() operators. Show the complete function that returns an AnyPublisher<Data, Never>.

Usage Example:

func fetchWithRetry(url: URL) -> AnyPublisher<Data, Never> {
    return URLSession.shared.dataTaskPublisher(for: url)
        .map(\.data)
        .retry(3)
        .catch { _ in
            Just(Data())
        }
        .eraseToAnyPublisher()
}

Conclusion

These 10 prompts cover the most common tasks in modern iOS development: SwiftUI views, UIKit components, Core Data persistence, Combine reactive programming, and testing. By using them as templates, you can reduce boilerplate and focus on your app's unique logic. Experiment with modifying the prompts to fit your specific project needs—add error handling, change UI styles, or include additional frameworks like Swift Charts or Vision.

Remember that AI-generated code should always be reviewed for security, performance, and adherence to your project's architecture. Use these prompts as a starting point, then refine the output with your expertise. Happy coding!

← All posts

Comments