LoginSignup
30
25

More than 3 years have passed since last update.

[iOS] frameとboundsの違いを理解する

Last updated at Posted at 2020-11-16

「frameとboundsの違いってなんやねん!」となったので調べました。

そもそもframeとboundsは

UIViewのサブクラスが持っているプロパティ。CGRectを返す。

英単語の意味的にはWeblio英和辞書によると

frame

a 窓枠.
b 額縁.
c 背景.
d (温床の)枠組み,フレーム,温床.
e (刺繍(ししゆう)などの)製作台,掛け枠.
f 複数形で(眼鏡の)枠,フレーム.
g (養蜂の取りはずし可能の)箱形のフレーム.

要するに"枠"という意味(?)

bounds

1境界,限界(内); 立ち入り許可区域.
2限度,範囲; 境界線,限界

という意味らしい

CGRectとは

公式ドキュメントによると

A structure that contains the location and dimensions of a rectangle.

と定義されており、
意訳すると
矩形の寸法を返す構造体となります。

frameとboundsの違いは

そもそもframeとboundsが何者かがわかったので、いよいよ本題です。

frame

要素自身を基準とした相対的な座標・大きさを返すプロパティ(superviewが基準)

bounds

要素の親を基準とした相対的な座標・大きさを返すプロパティ(UIView自身が基準)

という違いがあるみたいです。

つまりどこを基準とするかが変わってくるみたいです。

サンプルコード

実際にコードを書いて検証します。
x: 200, y: 200に正岡子規の画像を配置してframeとboundsの値の違いを見ます。

ViewController.swift
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let imageView = UIImageView(image: UIImage(named: "shiki"))

        // 指定した座標・大きさを設定
        imageView.frame = CGRect(x: 200, y: 200, width: 100, height: 100);

        print(
            "frameから見たX\(imageView.frame.minX)\n",
            "frameから見たY\(imageView.frame.minY)\n",
            "boundsから見たX\(imageView.bounds.minX)\n",
            "boundsから見たY\(imageView.bounds.minY)\n"
        )

        // viewにUIImageViewを追加
        self.view.addSubview(imageView)
    }

}

この位置に正岡子規が居る時、結果は
image.png

こうなりました。

座標は親要素をframeから見ると(200, 200)の所に、要素自身を基準にboundsから見ると(0, 0)で基準によって違うに対して大きさは一緒なのが分かります。

活用例

親要素を基準に子要素の大きさを指定することが出来ます。
また、こういった場合はframeよりboundsを使うほうが良いです。boundsは要素自身を基準とした座標・大きさを持っているからです。

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let imageView = UIImageView(image: UIImage(named: "shiki"))

        // 大きさ(親要素の半分の正方形)
        imageView.frame.size = CGSize(width: view.bounds.width / 2, height: view.bounds.height / 2)

        // 中心の座標(親要素の中心をframeから取る)
        imageView.center = CGPoint(x: view.bounds.width / 2, y: view.bounds.height / 2)

        // viewにUIImageViewを追加
        self.view.addSubview(imageView)
    }

}

注意点

また、UIViewを拡大・縮小したり、回転させるとframeの値は変わりますが、boundsの値は変わりません


    override func viewDidLoad() {
        super.viewDidLoad()
        let rectangle = UIView(frame: .zero)
        rectangle.backgroundColor = .blue
        rectangle.frame.size = CGSize(width: 100, height: 200)
        rectangle.center = CGPoint(x: view.bounds.width / 2, y: view.bounds.height / 2)
        // 拡大前
        print(rectangle.frame, rectangle.bounds) // (157.0, 348.0, 100.0, 200.0) (0.0, 0.0, 100.0, 200.0)

        rectangle.transform = CGAffineTransform(scaleX: 2, y: 2)

        // 拡大後
        print(rectangle.frame, rectangle.bounds) // (107.0, 248.0, 200.0, 400.0) (0.0, 0.0, 100.0, 200.0)

        view.addSubview(rectangle)
    }

このようにスケールさせた後、frameの値は変化しているのに対して、boundsの値が変化していないことが分かります。

参考文献

30
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30
25