이번에는 이전 포스팅에 배웠던 frame.origin과 bounds.origin을 실질적으로 옮겨보며
차이점을 조금 더 명확히 해보는 시간을 가져보자.
나의 똥손으로 시각자료를 만들려고 했지만.. 너무 좋은 자료가 있어서 이번 포스팅부터는
iOS 쪽 파워블로거 개발자 소들이님의 시각 자료를 이용해서 정리하는 것을 양해바란다. 🙏
1. frame origin을 변경할 경우
secondView의 frame.origin 값을 (20, 20) -> (50, 50)으로 변경해보자.
여기서 secondView는 입력한 대로 잘 이동 된 것을 볼 수 있다.
이 때 특이한 점은 thirdView 역시 이동한 것이다.
왜 이런 결과가 나올까? 이유는 이전 포스팅에서 배운 frame.orgin의 특성 때문이다.
frame.origin은 super view의 원점으로 부터 얼마나 떨어져 있는 지를 나타내닌 것이기 때문에
secondView의 frame.origin이 변경되면 그 SubView인 thirdView 역시 같이 그 만큼 움직인다.
정리하면 superView의 frame.origin이 이동하면 subView의 frame.origin도 역시 이동한다.
2. bounds origin을 변경할 경우
bounds.origin은 역시 (0, 0)으로 초기화 되어있다.
이번에도 역시 secondView의 bounds.origin을 (50, 50)으로 변경해보자.
우리가 학습한 내용으로는 thirdView는 움직이면 안된다. 그런데 움직이는 결과가 나왔다..
게다가 (50, 50)으로 양의 방향 (오른쪽, 아래로) 움직였는데
thirdView가 음의 방향(왼쪽, 위로) 반대로 움직였다.
왜 이런 결과가 나왔을까??
여기서 origin을 움직이라는 뜻은 viewport를 secondView의 자체 좌표계에서
(50, 50)으로 이동하라는 뜻이라고 한다.
여기서 생소한 단어 viewport를 알고 넘어가자.
viewport
화면이 보여지는 창 이라고 생각하면된다.
우리는 화면을 구성할 때 화면의 크기가 320 x 480일지라도
내가 원하는 View는 320 x 480 사이즈보다 더 넓게 그릴 수 있다.
소들이님 자료가 500 x 800으로 되어있으니 거기에 맞춰 해석해보자.
우리의 화면 size는 320 x 480로 작기 때문에 내가 그린 커더란 500 x 800의
view를 다 보여주지 못하고 320 x 480 만큼만 보여짐
이렇게 보여지는 밝은 부분을 viewport라고 한다.
다시 bounds.origin으로 돌아가 보면
bounds의 x,y 좌표를 바꾸는 것 = viewport의 x,y 좌표를 바꾸는 것
이라고 학습했다.
그렇다면 위 예제에서 bounds.origin을 (200, 200)으로 옮겨보자
옮긴 결과를 보면 viewport의 위치가 재대로 변경되었다.
여기서 첫번 째 주의사항은 viewport가 변경된 것이지
빨간 View와 파란 View의 frame이 변경된 것이 아니다.
두번 째 주의사항은 viewport를 이동하는 것이기 때문에
(200, 200)만큼 양의 방향(오른쪽, 아래쪽)으로 이동 했으나
실제 화면에선 마치 빨간 View, 파란 View가 (-200, -200)으로 이동 한 것처럼 보여진다.
그러면 첫번 째 예제 였던 왼쪽 결과가 이해가 되지 않는다. 오른쪽 결과가 맞지 않는가 ??
여기서 소들이님은 UIView는 자기자신의 크기만큼 viewport를 각각 갖고 있다고 가정하고 설명하신다.
블로그 글을 읽어보면 이런 가정이 왼쪽 결과를 이해하는데 도움이 된다.
view의 bounds.origin을 옮기는 것 = view의 viewport의 좌표를 움직이는 것
소들이님은 내 View의 Sub View를 어디에 담을지 움직이는 것 이라고 이해하고 계신다.
한번 다음 설명들을 이어서 봐보자
위 그림의 구조는 rootView -> firstView -> secondView -> thirdView로 구성되어있다.
각각의 view 입장에서 origin을 변경해보자.
1. rootView
rootView는 최상위 뷰이기 때문에 현재 기기의 화면 사이즈를 320 x 480이라 가정하다면
rootView의 viewport 역시 320 x 480이 된다.
만약 rootView의 bounds.origin을 (100, 100)으로 옮긴다면 어떤 결과가 나올까??
우리가 예상했던 결과가 정확히 일치하는 viewport 움직임이다.
오른쪽 하단으로 (100, 100)으로 이동했지만 (-100, -100)으로 이동한 것 같은 결과가 나온다.
2. firstView
fristView의 viewport는 역시 firstView의 사이즈와 같다.
이번에는 firstView 입장에서 (100, 100)으로 옮겨보자.
여기서 왜 subView가 firstView 바깥으로 밀러나갈까 ??
이것은 우리가 무의시적으로 사용했던 clipsToBounds를 false로 설정해서 그렇다.
한번 true로 고쳐보고 살펴보자.
firstView.clipsToBounds = true
옮겨진 viewport 기준으로 박으로 나간쪽은 잘려지는 것을 볼 수 있다.
이렇게되면 우리는 아무 의심없이 사용했던 clipsToBounds라는 property의 역할도 알 수 있게된다.
viewport 밖의 내용을 그리지(Draw) 않는다. 크기는 실제로 여전히 존재한다.
자세한 것은 소들이님 ClipsToBounds vs MasksToBounds 블로그를 참고하자.
3. secondView
마지막으로 secondView 기준으로 살펴보자.
secondView의 viewport 역시 secondView의 크기만큼 갖고 있다.
그 위치를 (50, 50)으로 옮겨보자.
정리
frame의 origin을 변경하면 subview의 frame 역시 이동되는 것을 알 수 있고
view의 origin을 변경한다는 것은
자기 자신은 가만히 있고 Sub View들이 반대 좌표로 이동하는 것이 아닌
해당 view가 자신의 sub view를 바라보는 시점(viewport)가 달라지는 것이다.
정말 헷갈리는 자료였는데 소들이님의 좋은 시각적 자료와 설명으로 이해가 많이되었다.
다음 학습은 그러면 frame과 bounds를 언제 쓰는지를 끝으로 frame과 bounds를 마무리해보자.
참고
'iOS > UIKit' 카테고리의 다른 글
UIGestureRecognizer (0) | 2024.09.05 |
---|---|
frame vs bounds (4) [ 사용 용도 ] (1) | 2024.09.02 |
frame vs bounds (2) [ 정의, 기준점, 크기 계산 방식] (0) | 2024.09.02 |
frame vs bounds (1) [ CGPoint, CGSize, CGRect ] (0) | 2024.09.02 |
생명주기 (4) [ 업데이트 Cycle ] (2) | 2024.09.01 |