Introduction
In modern iOS development, AI-assisted code generation can significantly speed up your workflow. Whether you're building with SwiftUI or UIKit, managing data with Core Data, or handling asynchronous events with Combine, the right prompt turns a vague idea into compilable, production-ready code. This collection contains 12 battle-tested prompts I use daily. Each includes a concrete example and a code snippet you can copy-paste into your Xcode project.
1. Generate a SwiftUI List with Pull-to-Refresh and Search
Prompt: "Create a SwiftUI view that displays a list of items fetched from a remote API. Include pull-to-refresh and a search bar that filters the list reactively."
Usage: Paste into ChatGPT, Claude, or Copilot while inside a Swift file. The model returns a complete view with @State, @Binding, and async/await calls.
struct ContentView: View {
@State private var items: [String] = []
@State private var searchText = ""
var body: some View {
NavigationView {
List(filteredItems, id: \.self) { item in
Text(item)
}
.searchable(text: $searchText)
.refreshable { await fetchItems() }
.navigationTitle("Items")
}
}
var filteredItems: [String] {
searchText.isEmpty ? items : items.filter { $0.contains(searchText) }
}
func fetchItems() async {
// Simulated network call
try? await Task.sleep(nanoseconds: 1_000_000_000)
items = ["Apple", "Banana", "Cherry"]
}
}
Source: Apple's Human Interface Guidelines for searchable and refreshable (developer.apple.com).
2. UIKit UICollectionView with Diffable Data Source
Prompt: "Write a UICollectionView with a compositional layout and a diffable data source that displays a grid of colored cells."
Usage: Use in a view controller viewDidLoad. The AI generates the layout, registration, and snapshot logic.
class GridViewController: UIViewController {
var collectionView: UICollectionView!
var dataSource: UICollectionViewDiffableDataSource<Int, Int>!
override func viewDidLoad() {
super.viewDidLoad()
configureHierarchy()
configureDataSource()
applyInitialSnapshot()
}
private func configureHierarchy() {
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.25), heightDimension: .fractionalHeight(1.0))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalWidth(0.25))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
let section = NSCollectionLayoutSection(group: group)
let layout = UICollectionViewCompositionalLayout(section: section)
collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout)
collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell")
view.addSubview(collectionView)
}
private func configureDataSource() {
dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView) { collectionView, indexPath, itemIdentifier in
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
cell.backgroundColor = [.red, .green, .blue, .yellow].randomElement()
return cell
}
}
private func applyInitialSnapshot() {
var snapshot = NSDiffableDataSourceSnapshot<Int, Int>()
snapshot.appendSections([0])
snapshot.appendItems(Array(0..<40))
dataSource.apply(snapshot, animatingDifferences: false)
}
}
Reference: WWDC 2019 session "Advances in UICollectionView".
3. Core Data Fetch with Predicate and Sort
Prompt: "Generate a Core Data fetch request for an entity named 'Task' with a predicate that filters by completion status and sorts by due date descending."
Usage: Place inside your NSManagedObjectContext extension or directly in a view model.
let request: NSFetchRequest<Task> = Task.fetchRequest()
request.predicate = NSPredicate(format: "isCompleted == %@", NSNumber(value: false))
request.sortDescriptors = [NSSortDescriptor(key: "dueDate", ascending: false)]
let context = PersistenceController.shared.container.viewContext
do {
let incompleteTasks = try context.fetch(request)
print("Found \(incompleteTasks.count) incomplete tasks")
} catch {
print("Fetch failed: \(error.localizedDescription)")
}
Best Practice: Always fetch on a background context for large datasets (Apple Core Data Programming Guide).
4. Combine Publisher to Observe Core Data Changes
Prompt: "Use Combine to observe changes from a Core Data context and publish the fetched results automatically."
Usage: Combine NSManagedObjectContext.didSaveObjectsNotification with a map operator.
import Combine
class TaskViewModel: ObservableObject {
@Published var tasks: [Task] = []
private var cancellables = Set<AnyCancellable>()
init(context: NSManagedObjectContext) {
NotificationCenter.default.publisher(for: .NSManagedObjectContextDidSave, object: context)
.map { _ in
let request: NSFetchRequest<Task> = Task.fetchRequest()
request.sortDescriptors = [NSSortDescriptor(key: "dueDate", ascending: true)]
return (try? context.fetch(request)) ?? []
}
.assign(to: &$tasks)
}
}
Source: Apple's Combine framework documentation "Receiving Notifications".
5. SwiftUI Image Picker with PHPickerViewController
Prompt: "Wrap PHPickerViewController in a SwiftUI representable to let the user pick images, then display the selected image."
Usage: Drop into your SwiftUI project as a reusable component.
struct ImagePicker: UIViewControllerRepresentable {
@Binding var image: UIImage?
func makeUIViewController(context: Context) -> PHPickerViewController {
var config = PHPickerConfiguration()
config.filter = .images
let picker = PHPickerViewController(configuration: config)
picker.delegate = context.coordinator
return picker
}
func updateUIViewController(_ uiViewController: PHPickerViewController, context: Context) {}
func makeCoordinator() -> Coordinator { Coordinator(self) }
class Coordinator: NSObject, PHPickerViewControllerDelegate {
let parent: ImagePicker
init(_ parent: ImagePicker) { self.parent = parent }
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
picker.dismiss(animated: true)
guard let provider = results.first?.itemProvider, provider.canLoadObject(ofClass: UIImage.self) else { return }
provider.loadObject(ofClass: UIImage.self) { [weak self] image, _ in
DispatchQueue.main.async { self?.parent.image = image as? UIImage }
}
}
}
}
Note: Import PhotosUI. This pattern is documented in Apple's "PHPickerViewController" guide.
6. SwiftUI Custom Modifier for Loading Indicator
Prompt: "Create a ViewModifier that overlays a loading spinner on any view when a condition is true."
Usage: Reusable across screens.
struct LoadingOverlay: ViewModifier {
let isLoading: Bool
func body(content: Content) -> some View {
content
.overlay(isLoading ? ProgressView().scaleEffect(1.5) : nil)
}
}
extension View {
func loadingOverlay(_ isLoading: Bool) -> some View {
modifier(LoadingOverlay(isLoading: isLoading))
}
}
Example usage: Text("Hello").loadingOverlay(true)
7. UIKit View Controller with Dynamic Type Support
Prompt: "Set up a UILabel with dynamic type that respects the user's preferred content size category."
Usage: Add to any view controller for accessibility.
let label = UILabel()
label.font = UIFont.preferredFont(forTextStyle: .body)
label.adjustsFontForContentSizeCategory = true
Reference: WWDC 2017 session "Building Apps with Dynamic Type".
8. Core Data Batch Delete for Performance
Prompt: "Perform a batch delete of all completed tasks without loading them into memory."
Usage: Call on a private background context.
let fetchRequest: NSFetchRequest<NSFetchRequestResult> = Task.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "isCompleted == YES")
let batchDelete = NSBatchDeleteRequest(fetchRequest: fetchRequest)
batchDelete.resultType = .resultTypeObjectIDs
let container = PersistenceController.shared.container
let backgroundContext = container.newBackgroundContext()
backgroundContext.perform {
do {
let result = try backgroundContext.execute(batchDelete) as? NSBatchDeleteResult
if let objectIDs = result?.result as? [NSManagedObjectID] {
NSManagedObjectContext.mergeChanges(fromRemoteContextSave: [NSDeletedObjectsKey: objectIDs], into: [container.viewContext])
}
} catch {
print("Batch delete failed: \(error)")
}
}
Why it matters: Batch operations do not fault objects, saving memory (Apple Core Data Performance).
9. Combine Debounce for Search Text
Prompt: "Use Combine's debounce to wait 300ms after the user stops typing before firing a search request."
Usage: In a SwiftUI view model.
@Published var searchText = ""
@Published var searchResults: [String] = []
$searchText
.debounce(for: .milliseconds(300), scheduler: RunLoop.main)
.removeDuplicates()
.sink { [weak self] text in
self?.performSearch(query: text)
}
.store(in: &cancellables)
Pro tip: Use removeDuplicates() to avoid redundant searches.
10. SwiftUI View with AsyncImage Placeholder
Prompt: "Display an image from a URL with a placeholder and error state using SwiftUI's AsyncImage."
Usage: Ready for any remote image.
AsyncImage(url: URL(string: "https://example.com/photo.jpg")) { phase in
if let image = phase.image {
image.resizable().scaledToFit()
} else if phase.error != nil {
Image(systemName: "photo").foregroundColor(.red)
} else {
ProgressView()
}
}
Availability: iOS 15+.
11. UIKit Programmatic Auto Layout with Anchors
Prompt: "Write NSLayoutConstraint anchors to center a button horizontally and place it 20 points below a label."
Usage: Inside viewDidLoad after adding subviews.
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
let button = UIButton(type: .system)
button.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(label)
view.addSubview(button)
NSLayoutConstraint.activate([
label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
label.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 100),
button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
button.topAnchor.constraint(equalTo: label.bottomAnchor, constant: 20)
])
See: Apple's Auto Layout Guide.
12. Core Data Lightweight Migration Setup
Prompt: "Configure the NSPersistentContainer to automatically perform lightweight migration when the model changes."
Usage: In your persistence controller.
let container = NSPersistentContainer(name: "MyDataModel")
let description = container.persistentStoreDescriptions.first
description?.setOption(true as NSNumber, forKey: NSMigratePersistentStoresAutomaticallyOption)
description?.setOption(true as NSNumber, forKey: NSInferMappingModelAutomaticallyOption)
container.loadPersistentStores { _, error in
if let error = error { fatalError("Unresolved error \(error)") }
}
Note: Only works for compatible changes (add/remove optional attributes, etc.).
Conclusion
These 12 prompts cover the most common tasks in iOS development with SwiftUI, UIKit, Core Data, and Combine. By integrating them into your daily workflow, you can reduce boilerplate code and focus on the unique logic of your app. Save this list for your next Xcode session.
Comments