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

If you're an iOS developer, you've probably spent hours searching Stack Overflow for the right way to animate a SwiftUI view or debug a Core Data fault. Large language models can accelerate that process — but only if you ask the right questions. A poorly phrased prompt leads to generic, sometimes incorrect code. A well-structured prompt acts like a senior engineer reviewing your work. This article gives you a set of battle-tested prompts for SwiftUI, UIKit, Core Data, and Combine, with concrete examples and explanations. I've used these with real projects and they map directly to Apple's official documentation (developer.apple.com) and Swift.org guides.

Why Prompting Matters for iOS

Apple's frameworks are huge. SwiftUI alone has over 2,000 modifiers, and UIKit still powers most production apps. A generic prompt like "make a login screen" gives you a forgettable result. But a prompt that specifies state management, dependency injection, and accessibility will return code that follows Apple's Human Interface Guidelines and Swift API Design Guidelines. The following examples are designed to be copy-paste modified for your own codebase.

12 Practical Prompts

1. SwiftUI View with MVVM and Combine

Prompt:

Create a SwiftUI view for a user profile screen. Use the MVVM pattern, combine @Published properties with Combine, inject a network service, and handle loading and error states. Include a preview with mock data.

Example result (key parts):

class ProfileViewModel: ObservableObject {
    @Published var profile: Profile?
    @Published var errorMessage: String?
    private let service: ProfileServiceProtocol

    init(service: ProfileServiceProtocol) {
        self.service = service
    }

    func load() {
        service.fetchProfile()
            .sink { [weak self] completion in
                if case .failure(let error) = completion {
                    self?.errorMessage = error.localizedDescription
                }
            } receiveValue: { [weak self] profile in
                self?.profile = profile
            }
            .store(in: &cancellables)
    }
}

Why it works: It forces the model to follow Apple's recommended MVVM pattern and includes error handling, a common oversight.

2. UIKit UITableView with Diffable Data Source

Prompt:

Implement a UITableView in UIKit that uses UITableViewDiffableDataSource for a contact list. Show how to perform snapshot updates when contact data changes. Use cells with custom styling.

Example with diffable datasource:

dataSource = UITableViewDiffableDataSource<Section, Contact>(tableView: tableView) { tableView, indexPath, contact in
    let cell = tableView.dequeueReusableCell(withIdentifier: "ContactCell", for: indexPath)
    cell.textLabel?.text = contact.name
    return cell
}

var snapshot = NSDiffableDataSourceSnapshot<Section, Contact>()
snapshot.appendSections([.main])
snapshot.appendItems(contacts)
dataSource.apply(snapshot, animatingDifferences: true)

3. Core Data Model and Fetch Request

Prompt:

Design a Core Data model for a Task app with attributes: name, dueDate, priority, and completed. Write an NSFetchRequest that filters tasks due today within a certain priority, sorted by due date. Include the managed object subclass.

Fetch request example:

let request: NSFetchRequest<Task> = Task.fetchRequest()
request.predicate = NSPredicate(format: "dueDate >= %@ AND dueDate <= %@ AND priority == %@", startOfDay, endOfDay, Priority.high.rawValue)
request.sortDescriptors = [NSSortDescriptor(key: "dueDate", ascending: true)]

4. Combine Operator Chain for Search

Prompt:

Write a Combine pipeline that reacts to a search text field in SwiftUI, debounces input by 300ms, removes duplicates, filters non-empty strings, and calls an API. Handle errors and cancellation.

Pipeline example:

$searchText
    .debounce(for: .seconds(0.3), scheduler: DispatchQueue.main)
    .removeDuplicates()
    .filter { !$0.isEmpty }
    .flatMap { query in
        api.search(with: query)
            .catch { error in
                Just([])
            }
    }
    .assign(to: \.results, on: self)

5. Unit Test for a ViewModel

Prompt:

Write unit tests for a SwiftUI ViewModel that uses Combine and a network service. Use mock service to test success, failure, and loading states. Use XCTest expectations to wait for Combine publishers.

Test example:

func testLoadSuccess() {
    let mockService = MockProfileService(result: .success(profile))
    let vm = ProfileViewModel(service: mockService)
    vm.load()
    expectation(for: \.profile, equals: profile)
    waitForExpectations(timeout: 1)
}

6. Performance: Reduce SwiftUI View Recomputations

Prompt:

Explain and demonstrate common reasons SwiftUI views get recomputed unnecessarily. Provide a visual example using a child view that doesn't depend on the changed state. Show use of @State, @ObservableObject, and Equatable.

Example: Use a child view that conforms to Equatable and pass a value type, which lets SwiftUI skip updates when the value hasn't changed.

7. Async/await Networking in Swift

Prompt:

Rewrite an existing URLSession dataTask-based networking code using Swift async/await. Show cancellation with URLSession.shared.data(from:) and handle errors with a custom error type.

Example:

func fetchData(from url: URL) async throws -> Data {
    let (data, response) = try await URLSession.shared.data(from: url)
    guard let http = response as? HTTPURLResponse, http.statusCode == 200 else {
        throw NetworkError.badServerResponse
    }
    return data
}

8. Accessibility in SwiftUI

Prompt:

Enhance a SwiftUI custom control (like a stepper) with accessibility labels, values, and actions. Show how to use accessibilityAdjustableAction to support VoiceOver gestures. Use the Accessibility Inspector tips from Apple's docs.

Example: Add .accessibilityValue(Text("Number: \(value)")) and implement accessibilityAdjustableAction to increment/decrement.

9. Debug Memory Leaks with Instruments

Prompt:

List the most common retain cycles in UIKit and SwiftUI. Write a debug helper that prints memory warnings. Explain how to use Xcode's Memory Graph Debugger to find leaks, and provide code for weak vs unowned.

Table: retain cycle sources

Pattern Issue Fix
Closures{ [weak self] in ... } self captured strongly use weak self
Timer with block timer retains self invalidate timer
Combine store(in:) used incorrectly use Set<AnyCancellable> with weak self

10. Migrate from SQLite to Core Data (or vice versa)

Prompt:

Compare Core Data vs SQLite for data persistence in an iOS app. Provide a migration plan and code for lightweight and heavyweight migration. Discuss zombie entities and external changes.

Key point: Core Data is not a database — it's an object graph persistence framework. Use lightweight migration for simple changes, and mapping model for complex ones.

11. Swift Concurrency in an Existing Codebase

Prompt:

Outline a strategy to incrementally move a UIKit project from callbacks and Combine to Swift Concurrency. Show how to wrap an existing method that uses @escaping completion handler into an async function using withCheckedThrowingContinuation.

Bridge example:

func legacyFetch(completion: (Result<Data, Error>) -> Void)

func asyncFetch() async throws -> Data {
    try await withCheckedThrowingContinuation { continuation in
        legacyFetch { result in
            continuation.resume(with: result)
        }
    }
}

12. Core Data Relationship and Model Design

Prompt:

Design a Core Data model for a blog with authors, posts, and comments. Show the proper inverse relationships and delete rules. Write a fetch request that gets all posts by a specific author with the comments count.

Relationship example: Set author.posts as inverse of post.author, delete rule cascade for comments.

Final Thoughts

These prompts work best when you treat them as a starting point. Modify them to include your exact model names, deployment targets, and edge cases. Apple's official documentation at developer.apple.com is the authoritative source for any API details; use LLM output as a companion, not a replacement. Start with a prompt that asks for a concrete, compilable example, then iterate by asking for test cases and performance considerations. That's how you turn a code generator into a productivity multiplier.

← All posts

Comments