WWDC22 SALE: Save 50% on all my Swift books and bundles! >>

CGSize and DragGesture question

Forums > 100 Days of SwiftUI

On Day 33, in the Animating with gestures video, Paul talks about using CGSize.zeo in a @State property called dragAmount but he doesn't really say why we're using it. He says it stands for Core Graphics which is an old Apple api and .zero represents no size, no width, no height. I can only assume from the code he produces that we're using CGSize because that's what DragGesture uses, but there really is no explanation. I've watched the video three times and I understand what he's doing but I have no idea what CGSize is. I looked in the Apple documentation but didn't really find anything helpful. Can anyone please provide a simple explanation?

One of his code examples from the video is below:

struct ContentView: View {
    let letters = Array("Hello, SwiftUI")
    @State private var enabled = false
    @State private var dragAmount = CGSize.zero

    var body: some View {
        HStack(spacing: 0) {
            //spacing: 0 - letters are side by side with no gap between them
            ForEach(0..<letters.count) { num in
                Text(String(letters[num]))
                    .padding(5)
                    .font(.title) //nice chunky font
                    .background(enabled ? .blue : .red)
                    .offset(dragAmount)  //so it will move around as our finger moves
                    .animation(
                        .default.delay(Double(num) / 20), //easeInOut delaying by our Index number in the letter array, 0 - 0sec, 20th - 1sec
                        value: dragAmount)
            }
        }
        .gesture(
            DragGesture()
                .onChanged{ dragAmount = $0.translation }
                .onEnded{ _ in
                    dragAmount = .zero
                    enabled.toggle() //causes color changes
                }
        )
    }
}

1      

The reason we use CGSize here is mentioned right in the documentation:

A CGSize structure is sometimes used to represent a distance vector, rather than a physical size.

So CGSize is used in drag operations to represent the vector of the drag in terms of x distance (width) and y distance (height).

Though why Apple chose to use CGSize for this instead of the already existing CGVector is a question for them.

1      

Thanks, for the responses. Basically, from what I understand, CGSize is a structure used for DragGestures(and possibly other things) for determining distance in 2d space and CGSize.zero is the start point. After reading the responses, I messed around with Xcode a little and ended up adding this to the HStack{} right before the getsture modifier to see how the values change.

.toolbar {
            ToolbarItem(placement: .bottomBar) {
                Text("h:\(dragAmount.height) w:\(dragAmount.width)")
            }
        }

1      

Thanks for the clarification.

struct ContentView: View {
    @State private var width = 0
    @State private var height = 0
    @State private var reset = false
    var body: some View {
        ZStack {
            Text("🐈‍⬛")
                .offset(reset ? CGSize.zero : CGSize(width: width, height: height))
            VStack {
                HStack {
                    Spacer()
                    Button {
                        reset = false
                        height -= 5
                    } label: {
                        Image(systemName: "arrow.up")
                    }
                    Spacer()
                }
                HStack {
                    Spacer()
                    Spacer()
                    Button {
                        reset = false
                        width -= 5
                    } label: {
                        Image(systemName: "arrow.left")
                    }
                    Button("Reset") {
                        reset = true
                        height = 0
                        width = 0
                    }
                    Button {
                        reset = false
                        width += 5
                    } label: {
                        Image(systemName: "arrow.right")
                    }
                    Spacer()
                    Spacer()
                }
                HStack {
                    Spacer()
                    Button {
                        reset = false
                        height += 5
                    } label: {
                        Image(systemName: "arrow.down")
                    }
                    Spacer()
                }
            }
        }
    }
}

1      

Yes! and No! CGSize is used for determining distance location in 2d space. CGSize.zero is not a starting point, it's the location of something in 2d space.

Well, no.

CGPoint indicates a location in a coordinate space.

CGSize indicates a distance vector to get to another point in the coordinate space.

Those can and often do have the same numeric values, but those values do not represent the same thing.

If you start with CGPoint(x: 0, y: 0) and offset it by CGSize(width: 100, height: 100) then you get to a new point CGPoint(x: 100, y: 100). So, coincidentally, your CGSize also tells you the new location.

But if you start with CGPoint(x: 100, y: 100) and offset it by CGSize(width: 100, height: 100), then your new point is at CGPoint(x: 200, y: 200) but your CGSize (i.e., your distance vector) is still 100x100.

So CGSize will tell you the absolute location if you happen to start from an origin point of 0,0. Otherwise, it only tells you the distance from your starting point to another point. (And CGSize.zero therefore indicates no movement from the starting point.) Admittedly, it can be a subtle distinction sometimes.

It's telling that DragGesture.Value has both a location property (represented with a CGPoint) and a translation property (represented by a CGSize).

Per Apple's docs:

location: "The location of the drag gesture’s current event."

translation: "The total translation from the start of the drag gesture to the current event of the drag gesture."

For those who don't remember their geometry, Wikipedia's got you covered: "a translation is a geometric transformation that moves every point of a figure, shape or space by the same distance in a given direction."

2      

Hacking with Swift is sponsored by Emerge

SPONSORED Why are Swift reference types bad for app startup time, and what’s the performance cost of protocol conformances? That’s just a couple of the topics you can learn about on the Emerge blog — written by the app performance experts behind Emerge’s advanced app optimization and monitoring tools, based on their experience of working at companies like Apple, Airbnb, Snap, and Spotify.

Find out more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.