Note Wisdom
These annotated notes walk through Stanford CS193p Lecture 6 SwiftUI data‑flow live coding. It covers Xcode refactoring, @State, @Binding pitfalls, component design, and previews Assignment 3 word‑game helper code.
Institution: Stanford
Original Course: Stanford CS193p: iOS Development with SwiftUI | 2025 | L6: Demonstrating Data Flow
Instructor Bio: This lecture is delivered by Paul Hegarty, Lecturer in Computer Science at Stanford University and the principal instructor of CS 193P since 2010. Paul Hegarty is a veteran software engineer and educator with deep roots in the Apple developer ecosystem. Earlier in his career he worked at NeXT Computer, where he contributed to the Objective-C language and the foundational tools that would eventually become Apple's modern development platform. He has taught iOS application development at Stanford for over fifteen years, guiding thousands of students through the transition from earlier UIKit frameworks to the modern SwiftUI declarative paradigm. He is widely recognized for his methodical teaching style, his emphasis on clean architectural patterns such as MVVM, and his ability to explain complex systems concepts through hands-on, live-coding demonstrations.
Course Description: This lecture is a hands-on demonstration that puts the data flow concepts from Lecture 5 into practice within the CodeBreaker application. It shows how to wire up observable view models, pass bindings between parent and child views, and manage shared state across multiple screens. The session also covers how to handle user input events, validate state transitions, and ensure that the UI remains consistent with the underlying model at all times, reinforcing the reactive programming model at the heart of SwiftUI.
@State, @Binding, good code organisation patterns, and debugging common pitfalls. Much of what is shown directly applies to Assignment 3, which builds a word‑guessing app similar to Wordle.Code struct from the model layer. Originally Code and CodeBreaker sat in the same model file. As Code gained more logic, it deserved its own dedicated file. You could manually make a new Swift file and copy‑paste, but the refactor tool automates that safely.PegView. The workflow is straightforward: copy the view code, make a new SwiftUI View template file, paste the drawing code, then add an incoming stored property to accept peg data. The preview canvas can supply sample peg data so you can see the component in isolation.// MARK:‑ comments. These do two practical things. First, they draw a thin divider line in your source file. Second, they add clickable markers in Xcode’s jump‑to‑file bar. His personal discipline is marking two sections in every view: incoming data, and the view’s body. This creates consistent mental separation as you manage SwiftUI data flow. I found this part really practical; it’s a low‑effort habit that makes scanning larger SwiftUI files much easier.reset() mutating function on the Code struct. The intended behaviour: after the user submits a guess, clear out the current guess pegs. All the logic lives in the model, not the view. Since SwiftUI’s UI is a reflection of model state, resetting model values automatically refreshes the screen, even picking up existing withAnimation animation wrappers.PegChooser.CodeBreakerView, so it becomes a @State private var. Remember: @State marks data owned by this view, its single source of truth. Marking it private is standard practice.setGuessPeg(peg:at:). This is a mutating model function that safely updates a peg at a given array index. He uses a guard statement to check if the index falls within valid array bounds. If the index is out‑of‑range, the function simply returns early, avoiding a runtime crash. He explains guard as a defensive coding tool: it protects the rest of your function from bad inputs, and signals to readers what pre‑conditions must hold for the subsequent code to run.opacity modifier created problems in dark mode; semi‑transparent layers would show whatever background sat underneath. To avoid opacity downsides, he creates a custom colour extension on SwiftUI’s Color type. The extension builds greys using hue‑saturation‑brightness initialiser, giving fully‑opaque light‑grey shades that work reliably in both light and dark appearance modes.structs inside your view, filled with static let constants. Group constants by purpose, for example a nested Selection struct for all values related to the selection highlight. This keeps magic numbers gathered in one spot, improves readability through descriptive names, and makes bulk tweaks simple. These nested constant structs live in the view file, but you could also move them out via extensions into separate files if your project grows very large.CodeBreakerView into a new CodeView. CodeView renders a whole row of pegs. Initially he copies the @State selection variable directly into CodeView. Once he runs the app, behaviour breaks.@State variables. Each view owned its own independent copy of selection. Tapping pegs changed one value; operating the peg chooser changed the other. They never synchronised. There were two separate sources of truth for one piece of application state.@Binding.
All contents below are exclusive to the paid Word file, NOT available on this web page
CodeView accepts a @Binding var selection: Int. A binding does not hold the source‑of‑truth itself. It acts as a reference conduit pointing back to the source‑of‑truth owned elsewhere. The original @State variable stays in CodeBreakerView. When instantiating CodeView, you pass $selection — the dollar‑sign syntax generates a binding reference to your state variable.@Binding properties cannot be private.@Binding cannot have default initial values, because the source‑of‑truth lives outside.var for bindings, not let, because you might write through the binding.let incoming properties are for read‑only data flowing into a view.PegChooser, he passes the entire model object (CodeBreaker) as a binding, plus also passes binding to selection. Functionally it worked, but it was bad design. The PegChooser only needs to know the list of available peg colours and to notify the parent when a colour gets selected. It does not need full read‑write access to the entire game model.PegChooser just displays colour options and reports when user picks one. It should receive the colour options as read‑only input (let choices: [Peg]), and accept a closure callback onChoose: (Peg) -> Void? for events. The optional closure means you could even use PegChooser as a static display widget with no interaction. All the logic for updating guess peg and advancing selection stays back in the parent view. The child component only fires the callback and knows nothing about game rules.PegChooser elsewhere without dragging the whole CodeBreaker model type along. This is one of the most important takeaways for Assignment 3.Code enum associated values so the master case carries an isHidden boolean. A computed property exposes this boolean. When the game ends (user guesses correctly), set isHidden to false to reveal the answer.isOver variable. It checks whether the last attempt’s pegs exactly match master code pegs. Since attempts.last returns optional, he demonstrates optional chaining syntax. If the attempts array is empty, .last becomes nil and the whole comparison evaluates to false.if statements inside body, so conditionally render the guess input UI only when the game is not over. Also reset selection index back to zero after submitting each guess.Words helper class. It can load a word list over network, check whether a string is valid word, and return random words of given length. This helper injects itself into SwiftUI’s environment values. You declare @Environment(\.words) inside a view to get access to the instance..onChange view modifier as the tool for reacting once the word count property changes. Until words finish loading you can fall back to a placeholder word. He notes the helper deals with networking errors and asynchronous logic, topics the course will cover in greater depth later.Words class is a reference‑type (class), not value‑type struct. He skips over what implications that has for SwiftUI view invalidation. If you mutate internal state inside that class, SwiftUI won’t automatically know to refresh views unless you manually trigger updates. That detail is glossed over in the lecture; I would probably need to read the provided assignment code sample to fully grasp that part.Skip hours of watching lectures. Get organized notes, exam prep materials and problem solutions all in one Word file.
Click to see everything included
All contents below are exclusive to the paid Word file, NOT available on this web page

