January 19, 2020

Difference between Frame and Bounds in Swift

Difference between Frame and Bounds in Swift

This is a question I have personally asked multiple times during my iOS development career. Today I will go over it, it is quite a simple answer, but there are some caveats to watch out for.

Let's start with the setup that I am using. I have placed a simple orange rectangle in the middle of the screen with Interface Builder and I have created an outlet for it called orangeView.

The next thing that I have done is to create a printAll method that will print the x, y, width and height of the orangeView. This print all will print that information for both the frame and the bounds so that we can see how it gets affected.

Add the following code:

private func printAll() {
    print("=========================")
    print("X : ", self.orangeView.frame.origin.x)
    print("Y : ", self.orangeView.frame.origin.y)
    print("width : ", self.orangeView.frame.size.width)
    print("height : ", self.orangeView.frame.size.height)
    print("=========================")
    print("X : ", self.orangeView.bounds.origin.x)
    print("Y : ", self.orangeView.bounds.origin.y)
    print("width : ", self.orangeView.bounds.size.width)
    print("height : ", self.orangeView.bounds.size.height)
    print("=========================")
}

If you call the above method from the viewDidLoad you should see something similar, the width and height of your frame and bounds will probably be different to mine, your x and y of your views frame will most likely be different compared to mine too, the x and y of your bounds should be the same as mine.

This is the output that I have when I run the project now:

=========================
X :  87.0
Y :  384.0
width :  240.0
height :  128.0
=========================
X :  0.0
Y :  0.0
width :  240.0
height :  128.0
=========================

As we can see the width and height of our frame and bounds are the same at the moment.

The next thing I want to do is rotate the orangeView, create a border based on the frame of the view and then we can get into the difference between frame and bounds.

I have added the below code just above where I called the printAll method:

self.orangeView.transform = CGAffineTransform(rotationAngle: 5)

If you build and run you should see something similar to this:

The output will also have changed, my console output looks like this:

=========================
X :  111.58938416597198
Y :  314.7747071707769
width :  190.82123166805604
height :  266.45058565844624
=========================
X :  0.0
Y :  0.0
width :  240.0
height :  128.0
=========================

Add the following code between printAll and self.orangeView.transform:

let testView = UIView(frame: CGRect(x: self.orangeView.frame.origin.x,
                                    y: self.orangeView.frame.origin.y,
                                    width: self.orangeView.frame.size.width,
                                    height: self.orangeView.frame.size.height))
testView.layer.borderColor = UIColor.red.cgColor
testView.layer.borderWidth = 2
self.view.addSubview(testView)

This will draw a red border based on the frame's location and size. If you build and run the app again you should see something similar to the following:

Now that we have the project setup, we can take a look at what is happening. Let's start off with the bounds.

In the picture above the bounds would represent the orange rectangle. The bounds of a view describes the views location and size in its own coordinate system.

This is what the Apple documentation says:

The bounds rectangle, which describes the view’s location and size in its own coordinate system.

Even when rotate the x, y, width and height will stay the same. The same cannot be said for frame.

The frame has to do with where the view is situated(location) within the parent view, but also, something like a rotation will affect it too.

The frame rectangle, which describes the view’s location and size in its superview’s coordinate system.

Let's talk about the location of the frame. When using the frame the x and y properties will represent where it is located within the parent view. If we rotate our view, the x and y coordinates will change.  

If we don't start changing the view or rotating it etc, the width and height will be the same as the bounds, but when we start doing things like rotation then it will all change.

You can think of the frame as a picture frame. The frame will be framing the view. So if we rotate the view, the frame will adjust its size in order to fit the rectangle, the same happens with the x and y coordinates. The frame will change because it try and wrap as tightly as possible around the view as you can see in the above image, the red border is perfectly sized to hold the orange rectangle.

Conclusion

bounds refers to the views coordinate system while the frame refers to the superviews coordinate system. Depending on the type of work that you are doing, this can have a big impact, but luckily it is something that should be quite obvious.

Full source code is available here.