No,Category,Guideline,Description,Do,Don't,Code Good,Code Bad,Severity,Docs URL
1,Views,Use struct for views,SwiftUI views are value types,struct MyView: View,class MyView: View,struct ContentView: View { var body: some View },class ContentView: View,High,https://developer.apple.com/documentation/swiftui/view
2,Views,Keep views small and focused,Single responsibility for each view,Extract subviews for complex layouts,Large monolithic views,Extract HeaderView FooterView,500+ line View struct,Medium,
3,Views,Use body computed property,body returns the view hierarchy,var body: some View { },func body() -> some View,"var body: some View { Text(""Hello"") }",func body() -> Text,High,
4,Views,Prefer composition over inheritance,Compose views using ViewBuilder,Combine smaller views,Inheritance hierarchies,VStack { Header() Content() },class SpecialView extends BaseView,Medium,
5,State,Use @State for local state,Simple value types owned by view,@State for view-local primitives,@State for shared data,@State private var count = 0,@State var sharedData: Model,High,https://developer.apple.com/documentation/swiftui/state
6,State,Use @Binding for two-way data,Pass mutable state to child views,@Binding for child input,@State in child for parent data,@Binding var isOn: Bool,$isOn to pass binding,Medium,https://developer.apple.com/documentation/swiftui/binding
7,State,Use @StateObject for reference types,ObservableObject owned by view,@StateObject for view-created objects,@ObservedObject for owned objects,@StateObject private var vm = ViewModel(),@ObservedObject var vm = ViewModel(),High,https://developer.apple.com/documentation/swiftui/stateobject
8,State,Use @ObservedObject for injected objects,Reference types passed from parent,@ObservedObject for injected dependencies,@StateObject for injected objects,@ObservedObject var vm: ViewModel,@StateObject var vm: ViewModel (injected),High,https://developer.apple.com/documentation/swiftui/observedobject
9,State,Use @EnvironmentObject for shared state,App-wide state injection,@EnvironmentObject for global state,Prop drilling through views,@EnvironmentObject var settings: Settings,Pass settings through 5 views,Medium,https://developer.apple.com/documentation/swiftui/environmentobject
10,State,Use @Published in ObservableObject,Automatically publish property changes,@Published for observed properties,Manual objectWillChange calls,@Published var items: [Item] = [],var items: [Item] { didSet { objectWillChange.send() } },Medium,
11,Observable,Use @Observable macro (iOS 17+),Modern observation without Combine,@Observable class for view models,ObservableObject for new projects,@Observable class ViewModel { },class ViewModel: ObservableObject,Medium,https://developer.apple.com/documentation/observation
12,Observable,Use @Bindable for @Observable,Create bindings from @Observable,@Bindable var vm for bindings,@Binding with @Observable,@Bindable var viewModel,$viewModel.name with @Observable,Medium,
13,Layout,Use VStack HStack ZStack,Standard stack-based layouts,Stacks for linear arrangements,GeometryReader for simple layouts,VStack { Text() Image() },GeometryReader for vertical list,Medium,https://developer.apple.com/documentation/swiftui/vstack
14,Layout,Use LazyVStack LazyHStack for lists,Lazy loading for performance,Lazy stacks for long lists,Regular stacks for 100+ items,LazyVStack { ForEach(items) },VStack { ForEach(largeArray) },High,https://developer.apple.com/documentation/swiftui/lazyvstack
15,Layout,Use GeometryReader sparingly,Only when needed for sizing,GeometryReader for responsive layouts,GeometryReader everywhere,GeometryReader for aspect ratio,GeometryReader wrapping everything,Medium,
16,Layout,Use spacing and padding consistently,Consistent spacing throughout app,Design system spacing values,Magic numbers for spacing,.padding(16) or .padding(),".padding(13), .padding(17)",Low,
17,Layout,Use frame modifiers correctly,Set explicit sizes when needed,.frame(maxWidth: .infinity),Fixed sizes for responsive content,.frame(maxWidth: .infinity),.frame(width: 375),Medium,
18,Modifiers,Order modifiers correctly,Modifier order affects rendering,Background before padding for full coverage,Wrong modifier order,.padding().background(Color.red),.background(Color.red).padding(),High,
19,Modifiers,Create custom ViewModifiers,Reusable modifier combinations,ViewModifier for repeated styling,Duplicate modifier chains,struct CardStyle: ViewModifier,.shadow().cornerRadius() everywhere,Medium,https://developer.apple.com/documentation/swiftui/viewmodifier
20,Modifiers,Use conditional modifiers carefully,Avoid changing view identity,if-else with same view type,Conditional that changes view identity,Text(title).foregroundColor(isActive ? .blue : .gray),if isActive { Text().bold() } else { Text() },Medium,
21,Navigation,Use NavigationStack (iOS 16+),Modern navigation with type-safe paths,NavigationStack with navigationDestination,NavigationView for new projects,NavigationStack { },NavigationView { } (deprecated),Medium,https://developer.apple.com/documentation/swiftui/navigationstack
22,Navigation,Use navigationDestination,Type-safe navigation destinations,.navigationDestination(for:),NavigationLink(destination:),.navigationDestination(for: Item.self),NavigationLink(destination: DetailView()),Medium,
23,Navigation,Use @Environment for dismiss,Programmatic navigation dismissal,@Environment(\.dismiss) var dismiss,presentationMode (deprecated),@Environment(\.dismiss) var dismiss,@Environment(\.presentationMode),Low,
24,Lists,Use List for scrollable content,Built-in scrolling and styling,List for standard scrollable content,ScrollView + VStack for simple lists,List { ForEach(items) { } },ScrollView { VStack { ForEach } },Low,https://developer.apple.com/documentation/swiftui/list
25,Lists,Provide stable identifiers,Use Identifiable or explicit id,Identifiable protocol or id parameter,Index as identifier,ForEach(items) where Item: Identifiable,"ForEach(items.indices, id: \.self)",High,
26,Lists,Use onDelete and onMove,Standard list editing,onDelete for swipe to delete,Custom delete implementation,.onDelete(perform: delete),.onTapGesture for delete,Low,
27,Forms,Use Form for settings,Grouped input controls,Form for settings screens,Manual grouping for forms,Form { Section { Toggle() } },VStack { Toggle() },Low,https://developer.apple.com/documentation/swiftui/form
28,Forms,Use @FocusState for keyboard,Manage keyboard focus,@FocusState for text field focus,Manual first responder handling,@FocusState private var isFocused: Bool,UIKit first responder,Medium,https://developer.apple.com/documentation/swiftui/focusstate
29,Forms,Validate input properly,Show validation feedback,Real-time validation feedback,Submit without validation,TextField with validation state,TextField without error handling,Medium,
30,Async,Use .task for async work,Automatic cancellation on view disappear,.task for view lifecycle async,onAppear with Task,.task { await loadData() },onAppear { Task { await loadData() } },Medium,https://developer.apple.com/documentation/swiftui/view/task(priority:_:)
31,Async,Handle loading states,Show progress during async operations,ProgressView during loading,Empty view during load,if isLoading { ProgressView() },No loading indicator,Medium,
32,Async,Use @MainActor for UI updates,Ensure UI updates on main thread,@MainActor on view models,Manual DispatchQueue.main,@MainActor class ViewModel,DispatchQueue.main.async,Medium,
33,Animation,Use withAnimation,Animate state changes,withAnimation for state transitions,No animation for state changes,withAnimation { isExpanded.toggle() },isExpanded.toggle(),Low,https://developer.apple.com/documentation/swiftui/withanimation(_:_:)
34,Animation,Use .animation modifier,Apply animations to views,.animation(.spring()) on view,Manual animation timing,.animation(.easeInOut),CABasicAnimation equivalent,Low,
35,Animation,Respect reduced motion,Check accessibility settings,Check accessibilityReduceMotion,Ignore motion preferences,@Environment(\.accessibilityReduceMotion),Always animate regardless,High,
36,Preview,Use #Preview macro (Xcode 15+),Modern preview syntax,#Preview for view previews,PreviewProvider protocol,#Preview { ContentView() },struct ContentView_Previews: PreviewProvider,Low,
37,Preview,Create multiple previews,Test different states and devices,Multiple previews for states,Single preview only,"#Preview(""Light"") { } #Preview(""Dark"") { }",Single preview configuration,Low,
38,Preview,Use preview data,Dedicated preview mock data,Static preview data,Production data in previews,Item.preview for preview,Fetch real data in preview,Low,
39,Performance,Avoid expensive body computations,Body should be fast to compute,Precompute in view model,Heavy computation in body,vm.computedValue in body,Complex calculation in body,High,
40,Performance,Use Equatable views,Skip unnecessary view updates,Equatable for complex views,Default equality for all views,struct MyView: View Equatable,No Equatable conformance,Medium,
41,Performance,Profile with Instruments,Measure before optimizing,Use SwiftUI Instruments,Guess at performance issues,Profile with Instruments,Optimize without measuring,Medium,
42,Accessibility,Add accessibility labels,Describe UI elements,.accessibilityLabel for context,Missing labels,".accessibilityLabel(""Close button"")",Button without label,High,https://developer.apple.com/documentation/swiftui/view/accessibilitylabel(_:)-1d7jv
43,Accessibility,Support Dynamic Type,Respect text size preferences,Scalable fonts and layouts,Fixed font sizes,.font(.body) with Dynamic Type,.font(.system(size: 16)),High,
44,Accessibility,Use semantic views,Proper accessibility traits,Correct accessibilityTraits,Wrong semantic meaning,Button for actions Image for display,Image that acts like button,Medium,
45,Testing,Use ViewInspector for testing,Third-party view testing,ViewInspector for unit tests,UI tests only,ViewInspector assertions,Only XCUITest,Medium,
46,Testing,Test view models,Unit test business logic,XCTest for view model,Skip view model testing,Test ViewModel methods,No unit tests,Medium,
47,Testing,Use preview as visual test,Previews catch visual regressions,Multiple preview configurations,No visual verification,Preview different states,Single preview only,Low,
48,Architecture,Use MVVM pattern,Separate view and logic,ViewModel for business logic,Logic in View,ObservableObject ViewModel,@State for complex logic,Medium,
49,Architecture,Keep views dumb,Views display view model state,View reads from ViewModel,Business logic in View,view.items from vm.items,Complex filtering in View,Medium,
50,Architecture,Use dependency injection,Inject dependencies for testing,Initialize with dependencies,Hard-coded dependencies,init(service: ServiceProtocol),let service = RealService(),Medium,
51,State,Use @Observable over ObservableObject,iOS 17+ macro for granular change tracking and better performance,@Observable class for view models,@Published @ObservedObject for new iOS 17+ projects,@Observable class UserViewModel { var name: String = "" },class UserViewModel: ObservableObject { @Published var name = "" },High,https://developer.apple.com/documentation/Observation/Observable()
52,Data,Use SwiftData for persistence,Modern persistence framework replacing Core Data with Swift-native syntax,@Model classes with SwiftData,Core Data with NSManagedObject for new projects,@Model class Item { var name: String; var timestamp: Date },class Item: NSManagedObject { @NSManaged var name: String? },High,https://developer.apple.com/documentation/swiftdata
53,Data,Use @Observable manager pattern with SwiftData,Centralize CRUD operations in Observable manager for testability,Manager class with @Observable and @ModelActor,Direct ModelContext manipulation in views,@Observable class DataManager { @MainActor func addItem() { context.insert(...) } },// Direct context.insert in Button action,Medium,https://developer.apple.com/documentation/swiftdata
54,UI,Use TipKit for user guidance,Framework for contextual tips and feature discovery,Tip protocol with rules and parameters,Custom tooltip implementations,"struct FeatureTip: Tip { var title: Text { Text(""New Feature"") } }",// Custom overlay with manual show/hide logic,Medium,https://developer.apple.com/documentation/tipkit
55,UI,Use TipGroup.ordered for sequential tips,iOS 18+ ordered tip groups for onboarding flows,TipGroup.ordered for multi-step onboarding,Manual tip ordering with state,TipGroup(.ordered) { FirstTip(); SecondTip(); ThirdTip() },// Custom state machine for tip sequence,Low,https://developer.apple.com/documentation/tipkit/tipgroup
56,Commerce,Finish transactions promptly,Clear transaction queue after delivering content,Finish transactions immediately after delivery,Leave transactions pending,for await result in Transaction.updates { await result.finish() },// Process transaction without calling finish(),High,https://developer.apple.com/documentation/storekit/transaction
57,Commerce,Use on-device verification,VerificationResult for on-device transaction validation,Check VerificationResult for valid transactions,Skip verification or server-only validation,case .verified(let transaction): // process,// Trust all transactions without verification,High,https://developer.apple.com/documentation/storekit/verificationresult
58,Integration,Define App Intents for system features,Enable Siri Shortcuts and Spotlight with App Intents,AppIntent protocol with parameters,UI-specific or redundant intents,struct BookHotelIntent: AppIntent { @Parameter var destination: String },// Intent that just opens the app without action,Medium,https://developer.apple.com/documentation/appintents
59,Performance,Use Lazy containers for lists,LazyVStack LazyHStack LazyVGrid for large data sets,Lazy containers for scrollable content,VStack with many items,LazyVStack { ForEach(items) { item in ItemRow(item) } },VStack { ForEach(items) { item in ItemRow(item) } } // loads all,High,https://developer.apple.com/documentation/swiftui/lazyvstack
60,Performance,Provide stable unique IDs for views,Stable identifiers enable efficient view diffing,Consistent id() for list items,Array indices as identifiers,ForEach(items) { item in Row(item).id(item.id) },"ForEach(items.indices, id: \.self) { i in Row(items[i]) }",Medium,https://developer.apple.com/documentation/swiftui/foreach
61,Animation,Use PhaseAnimator for multi-state animations,Cycle through animation phases with automatic or triggered transitions,PhaseAnimator for complex state sequences,Multiple withAnimation calls for phases,"PhaseAnimator([Phase.start, .middle, .end]) { phase in content.opacity(phase.opacity) }","withAnimation { state = .middle } // then later withAnimation { state = .end }",Medium,https://developer.apple.com/documentation/swiftui/phaseanimator
62,Animation,Use TimelineView for time-based animations,Sync animations to time updates for clocks countdowns and continuous effects,TimelineView with AnimationTimelineSchedule,Timer.publish for time-based updates,"TimelineView(.animation) { context in Circle().offset(x: sin(context.date.timeIntervalSince1970) * 50) }",Timer.publish(every: 0.016).autoconnect() // manual refresh,Medium,https://developer.apple.com/documentation/swiftui/timelineview
63,Animation,Use matchedGeometryEffect for seamless transitions,Create fluid hero transitions between views sharing same geometry ID,matchedGeometryEffect with @Namespace,Custom frame animations for transitions,"Image(name).matchedGeometryEffect(id: ""hero"", in: namespace)","withAnimation { selectedFrame = targetFrame } // manual position",High,https://developer.apple.com/documentation/swiftui/view/matchedgeometryeffect(id:in:properties:anchor:issource:)
64,Animation,Use KeyframeAnimator for keyframe sequences,Define precise keyframe tracks for complex multi-property animations,KeyframeAnimator for choreographed animations,Chained withAnimation delays,"KeyframeAnimator(initialValue: AnimationValues()) { value in content.offset(x: value.x) } keyframes: { KeyframeTrack(\.x) { ... } }","withAnimation(.delay(0.2)) { x = 10 } // chained delays",Medium,https://developer.apple.com/documentation/swiftui/keyframeanimator
65,Animation,Implement CustomAnimation protocol,Create reusable custom animation curves and behaviors,CustomAnimation for brand-specific easing,Inline animation configuration everywhere,"struct BounceAnimation: CustomAnimation { func animate<V>(value: V, time: TimeInterval, context: inout AnimationContext<V>) -> V? }",".animation(.timingCurve(0.68, -0.55, 0.27, 1.55)) // repeated inline",Low,https://developer.apple.com/documentation/swiftui/customanimation
66,Animation,Use spring(duration:bounce:) modifier,Modern spring animation API with intuitive duration and bounce parameters,spring(duration:bounce:) for predictable springs,Manual spring response/dampingFraction,.animation(.spring(duration: 0.5 bounce: 0.3)),.animation(.spring(response: 0.5 dampingFraction: 0.7)) // less intuitive,Medium,https://developer.apple.com/documentation/swiftui/animation/spring(duration:bounce:blendduration:)
67,iOS26,Apply glass material effects,Use Liquid Glass materials for depth and translucency in iOS 26,Material modifiers for glass effects,Solid opaque backgrounds for all surfaces,.background(.ultraThinMaterial).glassEffect(),.background(Color.white) // no depth,Medium,https://developer.apple.com/documentation/swiftui/material
68,iOS26,Use adaptive glass backgrounds,Implement context-aware glass that adapts to underlying content,GlassBackgroundEffect for adaptive translucency,Fixed opacity overlays,.background(GlassBackgroundEffect(in: .rect(cornerRadius: 16))),.background(Color.black.opacity(0.3)) // static,Medium,https://developer.apple.com/documentation/swiftui/view/glasseffect(_:in:isenabled:)
69,iOS26,Create liquid transitions,Use fluid morphing transitions between UI states,.liquidTransition() for state changes,Abrupt opacity/scale transitions,.transition(.liquidMorph),.transition(.opacity) // abrupt,Low,
70,iOS26,Layer vibrancy effects,Combine blur and vibrancy for readable overlaid content,.vibrant modifier with material backgrounds,Plain text over blurred backgrounds,"Text(""Label"").vibrant().background(.thinMaterial)","Text(""Label"").background(.thinMaterial) // low contrast",Medium,https://developer.apple.com/documentation/swiftui/vibrancyeffect
71,Performance,Optimize for 120Hz ProMotion,Ensure smooth animations on ProMotion displays with proper frame timing,High frame rate animations with .highFrameRateReason,30fps animations on 120Hz devices,.animation(.spring().highFrameRateReason(.tracking)),.animation(.spring()) // may not use full refresh rate,Medium,
72,Performance,Use CADisplayLink for frame-synced updates,Sync custom drawing to display refresh for tear-free rendering,CADisplayLink for custom real-time rendering,Timer for animation frames,"displayLink = CADisplayLink(target: self, selector: #selector(update)); displayLink.preferredFrameRateRange = CAFrameRateRange(minimum: 80, maximum: 120)",Timer.scheduledTimer(withTimeInterval: 1/60) // not display synced,Medium,https://developer.apple.com/documentation/quartzcore/cadisplaylink
73,Performance,Request adaptive refresh rates,Use preferredFrameRateRange for battery-efficient animations,Adaptive frame rates based on content motion,Fixed 120Hz for all content,"CAFrameRateRange(minimum: 30, maximum: 120, __preferred: 60)","view.preferredFramesPerSecond = 120 // battery drain",Low,https://developer.apple.com/documentation/quartzcore/caframeraterange
74,Icons,Use SF Symbols 5 effects,Apply built-in symbol effects like bounce pulse and variableColor,symbolEffect modifier for dynamic icons,Custom icon animations,Image(systemName: name).symbolEffect(.bounce trigger: triggerValue),Image(systemName: name).scaleEffect(animate ? 1.2 : 1.0) // manual,Medium,https://developer.apple.com/documentation/swiftui/view/symboleffect(_:options:value:)
75,Icons,Animate symbol transitions,Use contentTransition for smooth symbol changes between states,.contentTransition(.symbolEffect) for icon changes,Abrupt image swaps,"Image(systemName: iconName).contentTransition(.symbolEffect(.replace))",if condition { Image(icon1) } else { Image(icon2) } // abrupt,Medium,https://developer.apple.com/documentation/swiftui/contenttransition/symboleffect(_:options:)
76,Icons,Apply symbol rendering modes,Use hierarchical multicolor or palette rendering for rich SF Symbols,.symbolRenderingMode for visual depth,Monochrome symbols only,Image(systemName: name).symbolRenderingMode(.hierarchical),Image(systemName: name) // flat monochrome,Low,https://developer.apple.com/documentation/swiftui/symbolrenderingmode
77,Accessibility,Support Dynamic Type scaling,Ensure all text scales with user accessibility settings,@ScaledMetric for custom spacing and Dynamic Type fonts,Fixed font sizes and spacing,"@ScaledMetric(relativeTo: .body) var spacing: CGFloat = 16; .font(.body)","let spacing: CGFloat = 16; .font(.system(size: 16)) // fixed",High,https://developer.apple.com/documentation/swiftui/scaledmetric
78,Animation,Use interpolatingSpring for gesture-driven animations,Create springs that respond naturally to gesture velocity,.interpolatingSpring for drag-to-dismiss,Linear animations for gestures,.animation(.interpolatingSpring(stiffness: 300 damping: 30)),.animation(.linear) // unnatural feel on release,Medium,https://developer.apple.com/documentation/swiftui/animation/interpolatingspring(stiffness:damping:initiialvelocity:)