최근에 스크롤 뷰에 컨텐츠를 붙여 줌 인/아웃 패닝 등의 뷰의 Frame을 변경하여 미디어를 볼 수 있는 기능을 개발하다보니 특정 디바이스에서만 발생하는 UI프리징 비슷한 이슈가 있었다. 그러므로 좀 더 구체적으로 알아보고 UIScrollView는 어떻게 써야하는 지 확인해보자.
UIScrollView
UIScrollView에 포함된 뷰들의 확대&축소 및 스크롤링을 허용하는 뷰
UIScrollView는 몇몇 UIKit 클래스의 슈퍼클래스로 UITableView 혹은 UITextView같은 뷰 클래스들이 있다.
UIScrollView는 컨텐츠 뷰를 넘어서 조절할 수 있는 Origin을 가지는 뷰이다.
UIScrollView는 해당 스크롤 뷰의 프레임으로 컨텐츠를 자른다. 그리고 그 프레임은 보통 앱의 메인 윈도우와 일치한다.
UIScrollView는 손가락의 움직임을 추적하고 그에 상응하여 Origin을 조절한다.
UIScrollView를 통해 스크롤 뷰의 컨텐츠를 보여주는 뷰는 새 Origin에 따라 자기자신의 부분을 그린다. 그 Origin은 컨텐츠 뷰안에 offset으로 고정된 Origin이다.
UIScrollView는 수직/수평 스크롤 인디케이터를 제외하고는 어떠한 것도 스스로 그리지않는다.
UIScrollView는 컨텐츠 뷰의 사이즈를 반드시 알아야한다. 이유는 언제 스크롤링을 멈춰야할 지를 알아야하기 때문이다.
기본적으로 UIScrollView는 컨텐츠의 Bounds를 초과한 스크롤링을 할 때 바운싱을 한다.
스크롤 뷰 안에 보여질 컨텐츠의 그리는 것을 관리하는 객체는 컨텐츠의 서브뷰들을 쌓아올릴필요가 있다. 이유는 어떠한 뷰도 스크린의 사이즈를 넘어가서는 안되기 때문이다. 유저가 스크롤 뷰안에서 스크롤를 하면 이 객체는 필요에 따라 서브뷰를 제거하거나 추가한다.
UIScrollView는 스크롤 바들을 가지고있지 않기 때문에 컨텐츠 안에 서브뷰를 트랙하는 지, 스크롤을 하려는 지를 반드시 알아야한다.
이 결정을 내리기 위해, 스크롤 뷰는 일시적으로 타이머가 호출하기전에 타이머를 시작함으로써 유저의 터치 다운 이벤트를 가로챈다. 그리고 이건 터칭하고있는 손가락이 움직이는 지를 지켜보기 위함이다.
만약에 타이머가 특정 위치안에서 막대한 변화없이 호출한다면, 스크롤 뷰는 컨텐츠 뷰의 터치된 뷰들에게 Tracking 이벤트를 전송한다.
만약 유저가 타이머가 진행되기전에 충분히 먼 거리로 손가락을 드래깅했다면, 스크롤 뷰는 서브뷰안에 있는 Tracking을 취소하고 스크롤링을 수행한다.
서브클래스들은 touchesShouldBegin(_:with:in:), isPagingEnabled, touchesShouldCancel(in:) 를 오버라이딩해서 어떻게 스크롤 뷰가 스크롤링 제스쳐를 처리할지 결정할 수 있다.
UIScrollView는 또한 컨텐츠의 Panning과 Zooming을 처리한다. 유저가 핀치-인, 핀치-아웃 제스쳐를 사용함에 따라 스크롤 뷰는 컨텐츠의 Scale과 Offset을 조절한다. 제스쳐가 끝날 때, 컨텐츠 뷰를 관리하는 객체는 필요에 따라 컨텐츠의 서브뷰들을 업데이트한다(제스쳐는 손가락이 여전히 눌러져있더라도 끝날 수 있음을 명심해라). 제스쳐가 진행중일 때, 스크롤 뷰는 서브뷰들에게 어떠한 Tracking 콜도 보내지 않는다.
UIScrollView 클래스는 딜리게이트를 가질 수 있으며 가지기 위해서는 반드시 UIScrollViewDelegate를 준수해야한다.
Zooming과 Panning이 진행되기 위해서 딜리게이트는 반드시 viewForZooming(in:)과 scrollViewDidEndZooming(_:with:atScale:)을 구현해야한다.
추가적으로 maximumZoomScale과 minimumZoomScale은 반드시 달라야한다.
State Preservation
만약 너가 스크롤 뷰의 restorationIdentifier 프로퍼티에 값을 할당했다면, 스크롤 뷰는 앱이 런칭될 때 스크롤관련 정보를 보존한다.
특별히 zoomScale, contentInset, contentOffset 이 세가지 값은 보존된다. 복구중에 스크롤 뷰는 이 값들을 복구해서 컨텐츠는 이전과 동일한 위치에 스크롤이 된 상태로 나타난다.
위는 UIScrollView에 대한 애플 공식 문서이다. 하지만, 맨 첫 문장에서 언급했듯이 UI 프리징이 나타나는 케이스에서 문제는 zoomScale을 set했을 때 이후에 발생했으므로 zoomScale에 대한 더 구체적인 이해가 필요하다.
Zoomscale
스크롤 뷰의 컨텐츠에 적용시킬 현재 Scale 값을 지정하는 실수 값
이 값은 얼마나 컨텐츠가 현재 Scaled되어있는 지를 결정한다. 디폴트 값은 1.0이다.
'스위프트' 카테고리의 다른 글
[Swift] Swift에서의 프로토콜 사용의 다양한 예 (0) | 2022.08.08 |
---|---|
[Swift] Protocol에 대한 이해 및 정리 (0) | 2022.08.08 |
[UIKit] UIPageViewController의 뷰 컨트롤러 라이프 싸이클에 관해 (0) | 2022.06.13 |
[Swift] Concurrency (0) | 2022.03.15 |
[Swift] NSCoding, NSSecureCoding 고촬 (0) | 2022.03.11 |