iOS/개념

[iOS] Frame 과 Bounds의 차이

누알라리 2021. 1. 4. 23:13

개요

 

UI 코드를 짜면서 어쩔땐 frame... 어쩔땐 bounds.. 

기계적인 코딩을 피하고자 짚고 넘어갑니다.

앞서 알고있어야하는건 iOS의 좌표계의 기본은 top, left 입니다.

 

이 포스팅을 참고했습니다.

suragch.medium.com/frame-vs-bounds-in-ios-107990ad53ee

 

Frame vs Bounds in iOS

It all depends on your perspective

suragch.medium.com


Frame

 

상위 view의 좌표계를 기준으로한 view의 location, size

뷰를 부모안에 위치시킬 때 사용합니다.

 

액자 속의 사진을 상상합시다. (picture frame on a wall)

유저는 액자(Parent view)의 어느곳에나 사진(view)를 배치할 수 있습니다.

이는 parent view의 원점과 view의 원점을 동일시한다는 뜻입니다.


Bounds

view의 고유 좌표계를 사용하는 view의 location, size

뷰의 컨텐츠나 subView들을 해당 View에 위치시킬 때 사용합니다.

 

농구코트를 상상해봅시다..

때때로 농구는 out of bounds 넉아웃을 받습니다.

농구선수들은 공을 코트 안에서만 던지지만, 코트가 어디있는지는 전혀 상관할바가 아닙니다.

코트는 학교 운동장, 집 앞마당, 지하철 창구 안에 있을 수도 있습니다.

같은 맥락으로, view의 bounds의 좌표계는 오직 view 자신만 신경씁니다.

view가 parent view의 어디 있던지 상관하지 않습니다.

bounds의 원점은 view의 top, left 코너 입니다.

 

view안에 배치되는 모든 subview들은 이 원점과 관계가 생깁니다.


Example

[1]

Frame
    origin = (0, 0)
    width = 80
    height = 130
 
 Bounds 
    origin = (0, 0)
    width = 80
    height = 130

노란 사각형은 view의 frame을 뜻합니다.

우리가 나타내는 view는 현재 parent view의 원점에 위치하고 있습니다.

 

반면,

bounds쪽은 parent view에 대해 모르기 때문에 parent view가 나타나지 않습니다.

초록 사각형이 view의 bounds 입니다.

 

빨간 점은 frame, bounds의 원점 입니다.

 

[2]

 Frame
     origin = (40, 60) // That is, x=40 and y=60
     width = 80
     height = 130
 
 Bounds 
     origin = (0, 0)
     width = 80
     height = 130

frame을 사용하는 view는 parent view안에서 (40, 60)만큼 원점에 변화가 생겼습니다.

하지만 view의 이미지에는 변화가 없습니다. 

bounds는 아무 변화가 없습니다.

 


view에 transform을 적용하면 어떻게될까?

[3]

view에 시계방향으로 20도 정도 rotation을 적용시킵니다. 

Frame
   origin = (20, 52) // These are just rough estimates.
   width = 118
   height = 187
 
Bounds 
   origin = (0, 0)
   width = 80
   height = 130

bounds는 여전히 변화가 없습니다.

언제나 그랬듯이, frame안에 있는 view만이 변했습니다.

여기서 frame과 bounds의 차이점을 확실히 알 수 있습니다!

ashfurrow.com/blog/i-totally-didnt-understand-frames-and-bounds/

 

I Totally Didn't Understand Frames and Bounds

I was thinking about the overall architecture of iOS apps the other day, and it struck me just how much Cocoa Touch enforces use of the Model-View-Controller paradigm. Not just encourages , but actively enforces. A good example is your application delegate

ashfurrow.com

위 기사는 frame을 이렇게 정의하고 있습니다.

parent view의 좌표계에 대응하는 view의 모든 transformation이 포함된 view의 가장 작은 bounding box. 

제일 중요한것은 만약 view에 transformation (rotate, scale .. )을 먹인다면, frame은 undefined 된다는 겁니다.

무슨말이냐..

사실상, 위 사진의 돌아간 초록색 bounds 주위의 노란색 frame은 실제로는 존재하지 않는다는겁니다.

즉!

만약 개발자가 view에 transformation을 적용시킨다면 부모 view의 frame value는 더이상 사용하지 못한다는 겁니다.

하지만 여전히 bounds의 value들은 사용할 수 있습니다.

 

따라서 Apple은 경고합니다. (해석이 이게 맞나 싶어서 원문 첨부합니다..)

If a view’s transform property does not contain the identity transform, the frame of that view is undefined and so are the results of its autoresizing behaviors.
view의 transform 속성이 그 contents 자체의 transform이 아니라 외부 view 껍데기에 먹인거라면, view의 frame은 undefined 될것이며, 모든 작동의 결과는 autoresizing behavior의 결과일 것이다.

 

autoresizing이 적용된다면 하나 더 명심할 것이 있습니다.

view의 transfor 속성을 수정한다면, 모든 transformation들은 view의 center point를 기준으로 적용됩니다.

따라서 만일 개발자가 transfomration이 적용된 후에 parent view 안에서 view를 옮겨야 한다면, 개발자는 반드시 view의 center 좌표를 바꿔야합니다.

frame과 같게, center 또한 부모뷰의 좌표계를 사용합니다.

 


bounds의 원점은 항상 (0,0) 이었습니다.

view가 한번에 보여주지못할만큼 큰 subview를 가지면 어떻게 해야 될까요?

 

[4]

Frame
    origin = (40, 60)
    width = 80
    height = 130
 
Bounds 
    origin = (0, 0)
    width = 80
    height = 130

오직 view의 bounds안에 들어있는 top, left 코너에 위치한 이미지부분만 보이게 됩니다!!!

bounds의 원점을 바꾸면 어떻게 될까요?

Frame
    origin = (40, 60)
    width = 80
    height = 130
 
Bounds 
    origin = (280, 70)
    width = 80
    height = 130

parent view안에 있는 frame은 이동하지 않았지만 frame안의 컨텐츠는 바꼈습니다.

왜냐하면 bounds 사각형의 원점이 view의 다른 part에서 시작했기 떄문입니다.

 

이 개념은 UIScrollView와 그 서브 클래스(UITableView)에서 사용하는 개념과 동일한 개념입니다.

스크롤뷰를 우리가 나타내고 싶은 ParentView안에 넣고, 오토 레이아웃으로 frame의 위치를 조정해줍니다.

그리고 우리가 스크롤을 하면, 스크롤뷰의 bounds가 변하면서 스크롤뷰에 나오는 컨텐츠가 스크롤 되는 것입니다.

 


When to use frame and when to use bounds

 

frame이 parent view 안의 view의 location과 관련있기 때문에, 개발자는 outward change(외부의 작업)를 만들 때 사용하면 좋습니다. 예를들어, parent view와 view간의 width나 거리를 찾는 작업이요(?)

 

bounds는 inward change(내부의 작업)를 할 때 사용합니다.

무언가를 그리거나, view안에 subview들을 그릴때요. 또한 개발자는 transformation이 적용된 view의 사이즈를 얻을 때 사용할 수 있습니다.