The modern iOS toolchain
Xcode, Swift, and SwiftUI — what each one is, and the minimum you need to know before writing a line of code.
iOS development has exactly one required tool and it only runs on a Mac: Xcode, Apple's free IDE (the app where you'll write, run, and debug your code). Everything — writing code, designing the UI, running the simulator, and uploading to the App Store — happens inside it.
There is no supported way to build and submit an iOS app without macOS. A Mac mini, MacBook Air, or a cloud Mac (e.g. MacStadium) all work. Make sure it runs a recent macOS version and has room for Xcode — plan for 30+ GB of free disk. You do not need a physical iPhone to develop — the simulator is enough — but you'll want one to test the final build.
The three names you'll hear constantly
- Xcode — the application you install. It bundles the editor, the iOS Simulator, the compiler, and the tools that sign and upload your app.
- Swift — the programming language. Modern, readable, and strongly typed, which means the compiler catches many mistakes before the app runs. This is a gift when you're pairing with AI: bad AI code often won't even compile.
- SwiftUI — Apple's framework for building interfaces. You describe what the screen should look like for a given state, and the framework figures out how to draw and update it. It's declarative, which happens to be exactly the style AI writes well.
A useful mental model: Swift is the language, SwiftUI is a library written in that language for making screens, and Xcode is the workshop where you assemble everything.
The shape of a SwiftUI screen
Here is a complete, working SwiftUI screen. You don't need to understand every token yet — just notice that it reads top-to-bottom like a description of the UI:
import SwiftUI
struct ContentView: View {
// A piece of state. When it changes, the screen redraws itself.
@State private var name = ""
var body: some View {
VStack(spacing: 16) {
Text("Welcome to DayOne")
.font(.largeTitle)
.bold()
TextField("Your name", text: $name)
.textFieldStyle(.roundedBorder)
if !name.isEmpty {
Text("Hello, \(name)!")
.foregroundStyle(.secondary)
}
}
.padding()
}
}VStack stacks its children vertically. @State marks a value the view owns; when name changes, SwiftUI re-runs body and updates only what differs. The $name passes a two-way binding so the text field can write back into your state. Roughly 80% of SwiftUI is combinations of these ideas — stacks, state, and bindings.
You'll rely on AI to generate views like this. The value of understanding the shape above is that when a model gives you 60 lines, you can point at the wrong VStack and say "this should be an HStack" instead of regenerating blindly.