Learning Swift - Day Six

Done

The Goal

Today is day 6 of learning Swift. To start the day I began by finishing off my iOS 26 Programming for beginners book. There were some good nuggets in there about the liquid glass, split views etc… Today I’m continuing on with the Standford leactures - Leacture 7: Animation.


struct CodeView<AncillaryView>: View  where Ancillary: View {

    let ancillaryView: AncillaryView
    var body: some View {
        VStack {
            Text("This is in the view")
            ancillaryView // Renders the view that is passed in.
        }
    }
}

// We then can pass it in like:
CodeView(ancillaryView: Text("MAX"))
struct CodeViewTwo<AncillaryView: View>: View {
    let ancillaryView: AncillaryView

    init(@ViewBuilder ancillaryView: () -> AncillaryView) {
        self.ancillaryView = ancillaryView()
    }

    var body: some View {
        VStack {
            Text("This is in the view")
            ancillaryView
        }
    }
}

CodeViewTwo {
    Text("MAX")
}
struct CodeViewTwo<AncillaryView: View>: View {

    @ViewBuilder let ancillaryView: () -> AncillaryView

    var body: some View {
        VStack {
            Text("This is in the view")
            ancillaryView()
        }
    }
}

CodeViewTwo {
    Text("MAX")
}
fileprivate struct Selection {
    ...
}
struct CodeViewTwo<AncillaryView: View>: View {
    let ancillaryView: AncillaryView
    @Binding var selection: Int

    init(selection: Binding<Int>, @ViewBuilder ancillaryView: () -> AncillaryView) {
        self._selection = selection // So the reason we do _ is the binding above is already the computed value. So essentially the _selection means we can assign the selection init which is of type Binding<Int> to an int essentially.
        self.ancillaryView = ancillaryView()
    }

    var body: some View {
        VStack {
            Text("This is in the view")
            ancillaryView
        }
    }
}

// To provide the default value to this init you would do
struct CodeViewTwo<AncillaryView: View>: View {
    let ancillaryView: AncillaryView
    @Binding var selection: Int

    init(
        selection: Binding<Int> = .constant(3),
        @ViewBuilder ancillaryView: @escaping () -> AncillaryView = { EmptyView() }
    ) {
        self._selection = selection
    }

    var body: some View {
        VStack {
            Text("This is in the view")
        }
    }
}
struct CodeViewTwo<AncillaryView: View>: View {
    let ancillaryView: () -> AncillaryView

    // Basically saying ancillaryView is escaping this init
    init(@ViewBuilder ancillaryView @escaping: () -> AncillaryView) {
        self.ancillaryView = ancillaryView
    }

    var body: some View {
        VStack {
            Text("This is in the view")
            ancillaryView()
        }
    }
}

Animations

Text("Hello"!)
    .foregroundStyle(warning ? Color.red : Color.primary)
    .font(big ? .largeTitle : .caption)
    .animation(.easeInOut, value: warning) // .easeInOut is an animation struct.
Text("Hello"!)
    .foregroundStyle(warning ? Color.red : Color.primary)
    .font(big ? .largeTitle : .caption)
    .animation(.easeInOut, value: warning) // Animates when warning changes
    .padding(warning ? 10 : 0) // Doesn't get animated
    .animation(.easeInOut, value: big) // Doesn't animate the padding above because it is with the value warning
CodeView()
    .transaction { transaction in
        if code.kind == .master {
            transaction.animation = .none
        }

    }
ForEach(game.attempts) { attempt in
    CodeView(attempt)
        .transition(.asymmetric(insertion: .move(edge: top), removal: .identity))

}
@State private var selection = 0

view(for: game.guess)
    .onChange(of: selection, initial: false) {
        print("This change changes")
    }
.onChange(of: selection, intial: true) { oldValue, newValue in
    print("This selection change from \(oldValue) to \(newValue)!")
    if oldValue == newValue {}
}
TimelineView(.everyMinute) { context in
    Text("Stock price is \(stock.price)")
}