Author: saqibkhan

  • SwiftUI Layout Safe Area

    SwiftUI Layout: Safe Area

    Control content under system bars with .ignoresSafeArea() and .safeAreaInset().


    Safe Area

    Use .ignoresSafeArea() to control content under system bars.

    Example

    Demo.swift

    ContentView.swift

    App.swift

    import SwiftUI
    
    struct SafeAreaDemo: View {
      var body: some View {
    
    ZStack {
      LinearGradient(colors: [.blue, .purple], startPoint: .top, endPoint: .bottom)
        .ignoresSafeArea()
      Text("Hello safe area")
        .padding()
        .background(.ultraThinMaterial)
        .cornerRadius(8)
    }
    } }

    In the example above, the .ignoresSafeArea() modifier is used to control content under system bars.



    Safe Area Insets

    Insert UI at the edges (like a toolbar) using .safeAreaInset.

    Syntax:

    • .safeAreaInset(edge: .bottom) { content }

    Example

    Demo.swift

    ContentView.swift

    App.swift

    import SwiftUI
    
    struct SafeAreaInsetDemo: View {
      var body: some View {
    
    ZStack {
      LinearGradient(colors: [.purple, .pink], startPoint: .top, endPoint: .bottom)
        .ignoresSafeArea()
      Text("Content").padding().background(.ultraThinMaterial, in: Capsule())
    }
    .safeAreaInset(edge: .bottom) {
      HStack {
        Image(systemName: "house.fill"); Spacer(); Image(systemName: "gear")
      }
      .padding()
      .background(.regularMaterial)
    }
    } }
  • SwiftUI Layout GeometryReader

    SwiftUI Layout: GeometryReader

    Read parent size and position to build responsive layouts with GeometryReader.


    GeometryReader

    Use GeometryReader to read parent size and position to build responsive layouts.

    Example

    Demo.swift

    ContentView.swift

    App.swift

    import SwiftUI
    
    struct GeometryDemo: View {
      var body: some View {
    
    GeometryReader { geo in
      VStack(spacing: 12) {
        Text("Width: \(Int(geo.size.width))")
        Text("Height: \(Int(geo.size.height))")
      }
      .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
    .background(.orange.opacity(0.1))
    } }


    Responsive Positioning

    Position elements based on container size using GeometryReaderalignment, and offset.

    Syntax:

    • GeometryReader { geo in ... }
    • .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottomTrailing)
    • .offset(x: 0, y: -12)

    Example

    Demo.swift

    ContentView.swift

    App.swift

    import SwiftUI
    
    struct GeometryPositionDemo: View {
      var body: some View {
    
    GeometryReader { geo in
      ZStack {
        Color.orange.opacity(0.1)
        Text("Bottom Right")
          .padding(8)
          .background(.thinMaterial, in: Capsule())
          .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottomTrailing)
          .offset(x: 0, y: -12)
      }
    }
    } }
  • SwiftUI Layout Grids

    SwiftUI Layout: Grids

    Use LazyVGrid and LazyHGrid to arrange items in flexible grid layouts.


    Lazy Grids

    Lazy grids are used to display a large number of items in a grid layout.

    Syntax:

    • LazyVGrid(columns: columns, spacing: 12)
    • LazyHGrid(rows: rows, spacing: 12)

    Example

    Demo.swift

    ContentView.swift

    App.swift

    import SwiftUI
    
    struct GridDemo: View {
      let columns = [GridItem(.flexible()), GridItem(.flexible())]
      var body: some View {
    
    LazyVGrid(columns: columns, spacing: 12) {
      ForEach(1...6, id: \.self) { i in
        Text("Item \(i)")
          .frame(maxWidth: .infinity)
          .padding(12)
          .background(.blue.opacity(0.1))
          .cornerRadius(8)
      }
    }.padding()
    } }

    In the example above, the grid is created using a LazyVGrid with two columns, each with a flexible width.



    Adaptive Grid

    Use adaptive columns to fit as many items per row as space allows.

    Syntax:

    • [GridItem(.adaptive(minimum: 100))]
    • LazyVGrid(columns: columns) { ... }

    Example

    Demo.swift

    ContentView.swift

    App.swift

    import SwiftUI
    
    struct AdaptiveGridDemo: View {
      let columns = [GridItem(.adaptive(minimum: 100), spacing: 12)]
      var body: some View {
    
    LazyVGrid(columns: columns, spacing: 12) {
      ForEach(1...12, id: \.self) { i in
        Text("Card \(i)")
          .frame(maxWidth: .infinity, minHeight: 60)
          .background(.green.opacity(0.12))
          .cornerRadius(8)
      }
    }
    .padding()
    } }
  • SwiftUI Layout Frames & Padding

    SwiftUI Layout: Frames & Padding

    Control size and layout using .frame() and spacing using .padding().


    Fixed Frames

    Use fixed width and height to size content.

    Syntax:

    • .frame(width: 160, height: 60)

    Example

    Demo.swift

    ContentView.swift

    App.swift

    import SwiftUI
    
    struct FramesPaddingDemo: View {
      var body: some View {
    
    VStack(spacing: 16) {
      Text("Fixed size").frame(width: 160, height: 60).background(.blue.opacity(0.1))
      Text("Max width").frame(maxWidth: .infinity, alignment: .leading).padding(8).background(.green.opacity(0.1))
    }.padding()
    } }

    REMOVE ADS


    Flexible Frames and Alignment

    Use min/max constraints and alignment to size content responsively.

    Syntax:

    • .frame(minWidth: 120, maxWidth: .infinity, alignment: .trailing)
    • .frame(maxHeight: 120)

    Example

    Demo.swift

    ContentView.swift

    App.swift

    import SwiftUI
    
    struct FlexibleFramesDemo: View {
      var body: some View {
    
    VStack(spacing: 12) {
      Text("Trailing")
        .frame(minWidth: 120, maxWidth: .infinity, alignment: .trailing)
        .padding(8)
        .background(.gray.opacity(0.1))
        .cornerRadius(6)
      Text("Tall block")
        .frame(maxWidth: .infinity)
        .frame(maxHeight: 120)
        .background(.orange.opacity(0.1))
        .cornerRadius(6)
    }
    .padding()
    } }
  • SwiftUI Layout Spacers & Alignment

    SwiftUI Layout: Spacers & Alignment

    Use Spacer() to distribute content and alignment parameters to control placement.


    Spacers

    Use Spacer() to distribute content and alignment parameters to control placement.

    Example

    Demo.swift

    ContentView.swift

    App.swift

    import SwiftUI
    
    struct SpacersAlignmentDemo: View {
      var body: some View {
    
    HStack {
      Text("Left"); Spacer(); Text("Right")
    }
    .frame(maxWidth: .infinity, alignment: .leading)
    .padding()
    } }


    Vertical Alignment and Guides

    Align text baselines and customize positioning with alignment and alignmentGuide.

    Syntax:

    • HStack(alignment: .firstTextBaseline) { ... }
    • .alignmentGuide(.firstTextBaseline) { d in d[.bottom] }
    • VStack(alignment: .leading) { Spacer() }

    Example

    Demo.swift

    ContentView.swift

    App.swift

    import SwiftUI
    
    struct AlignmentGuideDemo: View {
      var body: some View {
    
    VStack(alignment: .leading, spacing: 16) {
      HStack(alignment: .firstTextBaseline, spacing: 8) {
        Text("Title").font(.title)
        Text("Aligned").alignmentGuide(.firstTextBaseline) { d in d[.bottom] }
      }
      HStack {
        Text("Left"); Spacer(); Text("Right")
      }
    }
    .padding()
    } }
  • SwiftUI Layout Stacks

    SwiftUI Layout: Stacks

    Arrange views vertically, horizontally, or in layers using VStackHStack, and ZStack.


    Examples

    Example

    Demo.swift

    ContentView.swift

    App.swift

    import SwiftUI
    
    struct StackDemo: View {
      var body: some View {
    
    VStack(spacing: 12) {
      Text("Title").font(.title)
      HStack {
        Text("Left")
        Spacer()
        Text("Right")
      }
      ZStack {
        Color.blue.opacity(0.1)
        Text("Overlay")
      }
    }.padding()
    } }


    Overlays and Alignment

    Layer content with ZStack and control placement using alignment and alignmentGuide.

    Syntax:

    • ZStack(alignment: .topLeading) { ... }
    • .alignmentGuide(.top) { d in d[.bottom] }

    Example

    Demo.swift

    ContentView.swift

    App.swift

    import SwiftUI
    
    struct OverlayDemo: View {
      var body: some View {
    
    ZStack(alignment: .topLeading) {
      Image(systemName: "rectangle.fill").resizable().foregroundStyle(.blue.opacity(0.15))
      Text("Badge")
        .padding(6)
        .background(.ultraThinMaterial, in: Capsule())
        .alignmentGuide(.top) { d in d[.bottom] } // custom guide
    }
    .frame(width: 220, height: 120)
    .padding()
    } }
  • SwiftUI Layout

    SwiftUI Layout

    Build flexible interfaces with stacks, frames, alignment, and spacing using SwiftUI’s layout system.


    Stacks and Spacing

    Use VStackHStack, and ZStack to arrange views vertically, horizontally, or in layers.

    Spacing and alignment are configurable.

    Syntax:

    • VStack(alignment: .leading, spacing: 8) { ... }
    • HStack { Text("A"); Spacer(); Text("B") }
    • ZStack { Color.blue; Text("Overlay") }

    Example

    Demo.swift

    ContentView.swift

    App.swift

    import SwiftUI
    
    struct StacksDemo: View {
      var body: some View {
    
    VStack(alignment: .leading, spacing: 12) {
      Text("Title").font(.title)
      HStack {
        Text("Left")
        Spacer()
        Text("Right")
      }
      ZStack {
        Color.blue.opacity(0.1)
        Text("Overlay")
      }
    }
    .padding()
    } }

    This example arranges content using vertical, horizontal, and layered stacks with titles, spacers, and padding.



    Frames and Alignment

    Adjust size and position with .frame().padding(), and .alignmentGuide.

    Syntax:

    • .frame(width: 200, height: 100)
    • .frame(maxWidth: .infinity, alignment: .leading)
    • .alignmentGuide(.firstTextBaseline) { d in d[.bottom] }

    Example

    Demo.swift

    ContentView.swift

    App.swift

    import SwiftUI
    
    struct FrameDemo: View {
      var body: some View {
    
    VStack(spacing: 16) {
      ZStack(alignment: .topLeading) {
        Color.yellow.opacity(0.2)
        Text("Top Left").padding(6)
      }
      .frame(width: 200, height: 100) // fixed size
      HStack {
        Text("Left")
        Spacer()
        Text("Right")
      }
      .frame(maxWidth: .infinity, alignment: .leading) // expand horizontally
      HStack(alignment: .firstTextBaseline, spacing: 8) {
        Text("Title").font(.title)
        Text("Aligned baseline")
          .alignmentGuide(.firstTextBaseline) { d in d[.bottom] }
      }
    }
    .padding()
    } }
  • iOS Project Setup

    iOS Project Setup

    Create a new SwiftUI app in Xcode, configure signing and capabilities, and set your deployment targets.


    Create a New Project in Xcode

    Use the App template, choose Swift and SwiftUI, set your organization identifier (e.g.

    com.example), and pick a bundle identifier like com.example.MyApp.

    Checklist

    • Product Name, Team, Organization Identifier
    • Interface: SwiftUI; Language: Swift; Use Core Data (optional)
    • Minimum iOS version (e.g. iOS 15+)

    Use this checklist to ensure your project is created with the right templates, identifiers, and minimum OS version.


    Run Examples in Xcode

    Standard workflow (used in this tutorial)

    Each example is organized into three files so you can run it as a small app:

    1. Demo.swift: The example’s main code (view and/or supporting types).
    2. ContentView.swift: Shows the demo (uses types from Demo.swift).
    3. App.swift: Stable entry point with WindowGroup { ContentView() }.

    Tip: In your own Xcode project, avoid duplicate ContentView declarations.

    Reuse a single ContentView and update its body per example, or create a simple chooser that navigates to uniquely named demo views.

    Optional: Canvas Preview

    You can also run any example via Xcode’s Canvas Preview without changing your app entry point.

    1. Create a SwiftUI View: File → New → File… → SwiftUI View. Paste the example view code.
    2. Add a Preview: Use a PreviewProvider or the #Preview macro.

    Example

    PreviewProvider.swift

    #Preview.swift

    import SwiftUI
    
    struct Demo_Previews: PreviewProvider {
      static var previews: some View { Demo() }
    }
    1. Open Canvas: Editor → Canvas. Build once if the preview is unavailable.
    2. Run & Interact: Click Resume/Play; use the device selector to switch models.

    Troubleshooting: If the preview fails to load, Build, then Clean Build Folder.

    Ensure the target is iOS and the file imports SwiftUI.



    Project Settings

    In the project navigator, select the app target and configure:

    • Signing & Capabilities: Select your team and enable automatic signing.
    • Deployment Info: Minimum iOS version, supported orientations.
    • Bundle Identifier: Matches the one you will register in App Store Connect.
  • SwiftUI Introduction

    SwiftUI Introduction

    Build interfaces declaratively with views, state, and data-driven updates using SwiftUI.


    What is SwiftUI?

    SwiftUI is Apple’s modern UI framework for building apps on iOS, iPadOS, macOS, watchOS, and tvOS.

    It is declarative: you describe what the UI should look like, and SwiftUI updates it when your data changes.


    Why SwiftUI?

    • Declarative syntax and reactive updates with @State@Binding, and ObservableObject.
    • Unified API across Apple platforms.
    • Live previews and fast iteration in Xcode.

    Building our First “App”

    First, you’ll build a simple counter view (ContentView) shown by the app entry (App.swift).

    Next, you’ll refactor the same UI but move its state into a view model (ObservableObject), which scales better in real apps.


    Step 1: Basic Example

    Syntax: Use @State for local state and bind it to controls (e.g., Button); render with VStack/Text.

    Example

    ContentView.swift

    App.swift

    import SwiftUI
    
    struct ContentView: View {
      @State private var count = 0
    
      var body: some View {
    
    VStack(spacing: 12) {
      Text("Count: \(count)")
      Button("Increment") { count += 1 }
    }
    .padding()
    } }

    This example shows a simple counter using @State and a button inside a VStack.

    About ContentView.swift: In SwiftUI, views live in ordinary .swift files.

    The starter view is typically named ContentView.swift, and the app’s entry point (App.swift) shows it in a WindowGroup.


    Step 2: State with ObservableObject

    Use ObservableObject to hold shared state, and @StateObject in the creating view to own its lifecycle.

    Views update automatically when @Published properties change.

    Syntax: class VM: ObservableObject { @Published var count }@StateObject private var vm = VM(), bind UI to vm.count.

    This example refactors the basic counter above.

    The UI and behavior are the same (a counter label and button), but the state now lives in a CounterModel view model managed by @StateObject. This pattern scales better as your app grows.

    Example

    Demo.swift

    ContentView.swift

    App.swift

    import SwiftUI
    import Combine
    
    class CounterModel: ObservableObject {
      @Published var count = 0
      func increment() { count += 1 }
    }

    This example promotes state into a ViewModel and updates the UI via @Published changes observed by the view.

    Platform look: SwiftUI adapts controls to the platform. On iOS the button appears as blue text; on macOS it’s a bordered push button. The behavior is the same.

    See iOS style in Xcode: run an iOS App target (iPhone simulator). If you’re in a macOS App and want a text-style button, add .buttonStyle(.plain) to the button.



    Run Examples in Xcode

    Standard workflow (used in this tutorial)

    Every example is organized into three files so you can run it as a small app:

    1. Demo.swift: The example’s main code (view and/or supporting types).
    2. ContentView.swift: Shows the demo (references types from Demo.swift).
    3. App.swift: Stable app entry with WindowGroup { ContentView() }.

    Tip: In your own Xcode project, keep a single ContentView. If you already have one from a previous example, reuse that file and update its body for the new demo. Alternatively, create a chooser menu and navigate to uniquely named demo views.

    Optional: Canvas Preview

    You can also run any example via Xcode’s Canvas Preview without changing your app entry point.

    1. Create a View file: In Xcode choose File > New > File… > SwiftUI View. Name it (for example, FrameDemo.swift) and paste the example view’s code into it.
    2. Add a Preview: Ensure the file has a preview. Use either a PreviewProvider or the #Preview macro.

    PreviewProvider.swift

    #Preview.swift

    import SwiftUI
      
      struct FrameDemo_Previews: PreviewProvider {
    
    static var previews: some View { FrameDemo() }
    }
    1. Open the Canvas: With the file selected, choose Editor > Canvas (or click the Canvas button). If you don’t see the preview, build the project once.
    2. Run the Preview: Click Resume / Play in the Canvas. Edits to the code will refresh the preview. Use the device picker to switch iPhone/iPad models.
    3. Interact: Previews are interactive—tap buttons, type into fields, etc.
  • Swift Memory Management

    Swift Memory Management

    Understand ARC, avoid retain cycles with weak/unowned, and manage closure captures safely.


    Automatic Reference Counting (ARC)

    Classes are reference types.

    Swift uses ARC to automatically track and release class instances when no strong references remain.

    Example

    class Box {
      let name: String
      init(_ n: String) { name = n; print("init \(n)") }
      deinit { print("deinit \(name)") }
    }
    
    do {
      let b = Box("A")
      print("in scope")
    }
    print("after scope")

    This example demonstrates ARC’s automatic deallocation of the Box instance when it goes out of scope.

    Tip: Use weak to avoid strong reference cycles between class instances.


    Strong Reference Cycles

    strong reference cycle occurs when two class instances hold strong references to each other, preventing ARC from deallocating them.

    Mark one side as weak (or unowned when appropriate) to break the cycle.

    Example

    class Person {
      let name: String
      var apartment: Apartment?
      init(name: String) { self.name = name }
      deinit { print("Person deinit") }
    }
    
    class Apartment {
      let unit: String
      weak var tenant: Person? // weak breaks the cycle
      init(unit: String) { self.unit = unit }
      deinit { print("Apartment deinit") }
    }
    
    do {
      var john: Person? = Person(name: "John")
      var unit: Apartment? = Apartment(unit: "4A")
      john!.apartment = unit
      unit!.tenant = john
      john = nil   // Person deinit
      unit = nil   // Apartment deinit
    }

    Declaring tenant as weak breaks the cycle so both objects deallocate when their strong references are set to nil.



    Closures and Capture Lists (weak self)

    Closures capture variables by default.

    When a class stores a closure that references self, use a capture list like [weak self] to avoid retain cycles.

    Example

    class Loader {
      var onComplete: (() -> Void)?
      func load() {
    
    // simulate async completion
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in
      guard let self = self else { return }
      print("Finished: \(self)")
      self.onComplete?()
    }
    } deinit { print("Loader deinit") } } do { let loader = Loader() loader.onComplete = { print("done callback") } loader.load() } // loader can be deallocated if nothing else references it