iOS Tutorials
Native iOS from an empty Xcode project to an app that ships — Swift and SwiftUI first, then everything a tutorial usually skips: the layer boundaries that keep a codebase readable, structured concurrency instead of callbacks, the Keychain, what a phone does to your app when it leaves the foreground, and how to test any of it. Every example is lifted from a working pizza ordering app, so code in these posts is code that runs.
- iOS – Interview QuestionsThe questions an iOS role actually asks, answered against the twenty-one lessons before this one. Struct versus class, what @State really stores, how SwiftUI decides to redraw, retain cycles in closures, what @MainActor guarantees, actor reentrancy, and how you would make a screen testable. Short answers, with the reasoning.
- iOS – Build Configuration, CI and Shippingxcconfig files so a build setting is reviewable, Info.plist keys a custom plist makes you own, signing and what actually needs an Apple account, a CI workflow that checks the committed project still matches its manifest, and the archive-to-App-Store path with the rejections worth avoiding.
- iOS – Previews, Linting and the Tools Around the CodeA preview that needs a running backend is a preview nobody uses. Stub repositories so every screen renders instantly — including its failure state — plus SwiftLint and SwiftFormat configured to catch what review keeps catching, and the Instruments templates worth knowing before you need them.
- iOS – Testing an iOS AppWhat to test and what to skip. Pure rules first because they cost nothing, a real URLSession against a stubbed URLProtocol so the assertions are about the bytes you would send, hand-written doubles over a mocking framework, testing async and main-actor code, and why @MainActor on an XCTestCase is wrong.
- iOS – AccessibilityA drawn control carries no meaning. Labels, values, traits and the difference between them, combining a row into one announcement and the trap that hides its button, Dynamic Type, touch target size, and how to check any of it in about a minute — with the real controls in this app that needed each fix.
- iOS – Taking Payments with StripePaymentSheet rather than a card form of your own, and the PCI reason that is not negotiable. The two-step order-then-pay flow and why it has to be two steps, quarantining the SDK behind a protocol so checkout is testable, bridging a completion handler into async, and the dismissed sheet that is not an error.
- iOS – The App Lifecycle and What a Phone Does to YouA browser tab lives until it is closed; your app can be suspended mid-sentence and killed without warning. scenePhase, the write you have to flush before backgrounding, the launch gate an async Keychain read forces on you, and the startup ordering that is load-bearing rather than tidy.
- iOS – Persistence, UserDefaults and the KeychainWhere each thing belongs and why the split is a security decision, not a convenience one. UserDefaults for preferences, the Keychain for a session token, the accessibility class that actually matters, and why the Security API makes you write save as delete-then-add. Plus what SwiftData is for.
- iOS – Dependency Injection Without a FrameworkA composition root — one initialiser that decides every concrete type the app runs with — instead of singletons scattered through it. Why a static shared is a testing problem before it is a design problem, injecting through the SwiftUI environment, and the constructor parameter that turns an ordering rule into a compiler guarantee.
- iOS – Architecture: Layers That HoldMVVM is not an architecture, it is a naming convention for one third of one. The layering underneath it: domain models and rules that import nothing, repository protocols the features depend on, implementations they never see, and a pure reducer for the one piece of state worth being strict about.
- iOS – async/await, Tasks and ActorsStructured concurrency in the shape you will actually use it: async let for requests that should overlap, .task tying work to a view's lifetime, cancellation you get for free, @MainActor and what it enforces, and an actor for state several callers touch at once. Plus the deinit rule nobody mentions.
- iOS – Error Handling That Reaches the UserA typed error whose cases are the decisions a caller can make, not the places it went wrong. LocalizedError, field-level messages from a server, telling a cancelled request apart from a failed one, and the ViewState enum that makes the eternal spinner impossible to write.
- iOS – Networking with URLSessionOne type that performs requests, and everything else describing them. An Endpoint as inert data so routes are testable without a socket, async/await over URLSession, Codable and the decoding failures that only happen in production, and configuration that comes from the build rather than a constant.
- iOS – Building a Design SystemTokens, a semantic layer over them, and components that consume the semantic layer — the three tiers, and why skipping the middle one makes a retune impossible. ViewModifier versus wrapper view, ButtonStyle instead of a custom button, and writing a Layout by hand when SwiftUI ships nothing that wraps.
- iOS – Sheets, Modals and Alertssheet(isPresented:) versus sheet(item:), and why the second one resets a form for free. Detents, drag indicators, alerts and confirmation dialogs, and the boolean-flag mistake that makes a tap look like it was dropped — with the one enum that makes it unrepresentable.
- iOS – Forms, Text Input and ValidationThe keyboard is part of your UI. keyboardType, textContentType and AutoFill, the autocapitalisation default that breaks every email field, @FocusState and moving between fields, and a validation model that keeps the rules out of the view and testable in microseconds.
- iOS – Lists, Grids and Keeping Them FastList, LazyVStack and LazyVGrid, and the difference that matters: which of them builds every row before showing you the first one. Identity and why a bad id is a rendering bug, pull-to-refresh, and what SwiftUI does instead of React's memo — including what you still have to do yourself.
- iOS – NavigationNavigationStack with a path, so a route is a value you can push, log and restore rather than a view built eagerly for a row nobody tapped. Typed routes, tabs that each keep their own stack, programmatic navigation after a payment, and where deep links plug in.
- iOS – State, @Observable and Data Flow@State, @Binding, @Observable and @Environment: which one to reach for, and the rule that decides it. Why @Observable replaced ObservableObject and what it actually changed, @Bindable, and the line between state a screen owns and state the app owns — with the three stores this app has and the many it deliberately does not.
- iOS – SwiftUI Views and LayoutA View is a value, not an object, and almost everything surprising about SwiftUI follows from that. Stacks, frames and the layout conversation between parent and child, modifier order and why it is not decoration, and how to build a reusable container — the card every screen in this app is made of.
- iOS – The Swift You Need FirstNot the whole language — the parts a SwiftUI app leans on every day. Value types versus reference types and why it changes how you reason about a screen, optionals, enums with associated values, protocols and extensions, closures, and the error model. With the models of a real ordering app as the running example.
- iOS – Getting StartedWhat you actually need to build an iOS app, what each piece of Xcode is for, and the anatomy of a project — targets, schemes, build configurations and the .xcodeproj nobody can read. Ending with a project generated from a manifest instead, so a build setting change is a line in a diff rather than an opaque edit.