Irbisa · Cheatsheet
SwiftUI Fundamentals
View protocol, modifiers, layout containers, navigation, lists
What is SwiftUI, and what are its advantages and drawbacks compared with UIKit?
What does declarative UI mean, and why are SwiftUI views structs rather than classes?
What is the
Viewprotocol, what isbody, and what doessome Viewmean?struct ProfileHeader: View { let name: String let isPro: Bool // The real type is VStack<TupleView<(Text, Text?)>>; `some View` hides it var body: some View {…What do
@main,AppandScenedo in a SwiftUI app?@mainstruct NotesApp: App { @State private var store = NotesStore() // @Observable model owned by the app @UIApplicationDelegateAdaptor(AppDelegate.self) private var appDelegate @Environment(\.scenePhase) private var scenePhase…How do
VStack,HStackandZStacklay out their children, and when do you needLazyVStackinstead?VStack(alignment: .leading, spacing: 4) { Text("Title").font(.headline) Text("Subtitle").foregroundStyle(.secondary)} HStack {…What does each of these three badges look like, and why does swapping two modifiers change the result?
// Badge AText("Sale") .padding() .background(.red) // Badge BText("Sale") .background(.red) .padding() // Badge CText("Sale") .background(.red) .frame(width: 200)How do you write a reusable style in SwiftUI: a custom
ViewModifieror aButtonStyle?struct CardStyle: ViewModifier { func body(content: Content) -> some View { content .padding() .background(.regularMaterial, in: .rect(cornerRadius: 16)) }…You stretched a
Textwith.frame(maxWidth: .infinity)and it stayed centred. How do the different alignments in SwiftUI differ?// wrong: the frame stretches, the text stays in its centreText("Title").frame(maxWidth: .infinity) // right: tell the frame where to put its childText("Title").frame(maxWidth: .infinity, alignment: .leading)…A bundled
Imageignores its.frameand.scaledToFill()spills over neighbours; in what order do the modifiers go, and what doesAsyncImagenot do for you?// wrong: a bundled image ignores the proposed size until it is resizableImage("cover").frame(width: 120, height: 120) // full size, overflowing // right: resizable, content mode, frame, then clip what .fill spillsImage("cover") .resizable()…How do you build a
ListwithForEach, and why does every row need a stableid?struct Todo: Identifiable { let id: UUID // stable: stored on the model, not generated in body var title: String var isDone = false}…How do you build a form in SwiftUI with
TextField,SecureField,ToggleandPicker?struct SignUpForm: View { @State private var email = "" @State private var password = "" @State private var plan: Plan = .free @State private var wantsNews = false…How do you present a sheet or an alert in SwiftUI, and when do you use the
item:form instead ofisPresented:?struct InboxView: View { @State private var editing: Message? // nil means no sheet @State private var pendingDelete: Message? var body: some View { List(messages) { message in…When do you use
LazyVGridand whenGrid, and how do you make the column count follow the screen width?// Gallery: as many 120-pt columns as fit, cells built lazilyScrollView { LazyVGrid(columns: [GridItem(.adaptive(minimum: 120), spacing: 8)], spacing: 8) { ForEach(photos) { photo in Thumbnail(photo).frame(height: 120) }…How do you write SwiftUI previews for a view with several states or a service dependency?
#Preview("Default") { ProfileCard(user: .preview)} #Preview("Long bio, largest text") { ProfileCard(user: User(id: UUID(), name: "Alice",…When do you use a
List, and when aScrollViewwith aLazyVStack?How does SwiftUI decide a view's size: who has the final say, the parent or the child?
// .frame proposes a size and positions whatever the child returnsText(longString).frame(width: 100) // Text wraps into 100 pt // fixedSize asks for the ideal size: stop the vertical truncationText(paragraph) .fixedSize(horizontal: false, vertical: true)…How does
NavigationStackwork, and how do you navigate programmatically or from a deep link?enum Route: Hashable { case profile(userID: String) case settings} struct RootView: View {…Tapping a row in this list does nothing, and Xcode logs a navigation warning: what is wrong?
struct ShopView: View { let products: [Product] var body: some View { NavigationStack { List(products) { product in NavigationLink(product.name, value: product) .navigationDestination(for: Product.self) { product in ProductDetail(product: product) } } .navigationTitle("Shop") } }}What does this code print when the screen appears and on each tap, and what does that tell you about
init,bodyandonAppear?struct Child: View { init() { print("init") } var body: some View { let _ = print("body") Text("Child").onAppear { print("appear") } }} struct Parent: View { @State private var count = 0 var body: some View { VStack { Text("Taps: \(count)"); Child(); Button("Tap") { count += 1 } } }}Find the bug: each time the user comes back to this screen the stopwatch counts faster, and it keeps ticking while another screen is on top.
struct StopwatchView: View { @State private var seconds = 0 var body: some View { Text("\(seconds) s") .font(.largeTitle.monospacedDigit()) .onAppear { Task { do { while true { try await Task.sleep(for: .seconds(1)) seconds += 1 } } catch {} } } }}What is
@ViewBuilderdoing behind the scenes, and why is returningAnyViewa bad habit?// Your own container that takes a builderstruct Card<Content: View>: View { @ViewBuilder var content: Content var body: some View { VStack(alignment: .leading, spacing: 8) { content }…What is the difference between
withAnimationand the.animationmodifier, and why was the single-argument.animation(_:)deprecated?struct Panel: View { @State private var isExpanded = false @State private var count = 0 var body: some View { VStack {…A list row has a star button and a delete button, and tapping either one runs both plus the row's navigation: what is happening?
// wrong: .automatic buttons inherit the row's tap regionList(messages) { message in NavigationLink(value: message) { HStack { Text(message.title) Spacer()…After saving on the fourth pushed screen you must land back on the root, and the same flow also runs inside a sheet: how do you build that?
@Observable @MainActorfinal class Router { var path: [Route] = [] } struct RootView: View { @State private var router = Router() @State private var sheetRouter = Router()…Find the bug: picking another article updates the title, but this web view keeps showing the first page.
struct WebView: UIViewRepresentable { let url: URL func makeUIView(context: Context) -> WKWebView { let webView = WKWebView() webView.load(URLRequest(url: url)) return webView } func updateUIView(_ webView: WKWebView, context: Context) {}} // In the parent: WebView(url: selectedArticle.url)