Swift UIKit 스크롤뷰 코드로 구현하기

  • WebView의 스크롤뷰에 뷰를 추가하는 작업을 하게되었다.
  • 이 과정에서 스크롤뷰를 Swift로 programmatically 구현하게 되었는데, 이를 복습하고자 한다.

ViewController에 ScrollView 추가

  • 일반적인 스크롤뷰를 뷰컨트롤러에 추가하는 방법은 다음과 같다.
  • 우선 필요한 컴포넌트를 생성한다.
let labelOne: UILabel = {
  let label = UILabel()
  label.text = "Scroll Top"
  label.backgroundColor = .red
  label.translatesAutoresizingMaskIntoConstraints = false
  return label
}()

let labelTwo: UILabel = {
  let label = UILabel()
  label.text = "Scroll Bottom"
  label.backgroundColor = .red
  label.translatesAutoresizingMaskIntoConstraints = false
  return label
}()

let scrollView: UIScrollView = {
  let scrollView = UIScrollView()
  scrollView.backgroundColor = .blue
  scrollView.translatesAutoresizingMaskIntoConstraints = false  
  return scrollView
}()
  • viewDidLoad() 라이프 사이클에 오토레이아웃을 추가한다.
override func viewDidLoad() {
  super.viewDidLoad()

  self.view.backgroundColor = .yellow
  self.view.addSubview(scrollView)

  scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20).isActive = true
  scrollView.topAnchor.constraint(equalTo: view.topAnchor, constant: 20).isActive = true
  scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20).isActive = true
  scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -20).isActive = true

  scrollView.addSubview(labelOne)

  labelOne.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 40).isActive = true
  labelOne.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 40).isActive = true

  scrollView.addSubview(labelTwo)

  labelTwo.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 40).isActive = true
  labelTwo.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 1000).isActive = true
  labelTwo.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: -40).isActive = true
}
  • 이 코드로 나온 결과물은 다음과 같다.
swift-scrollview-programmatically

WebView의 ScrollView

  • 다음 구조와 같이 WebView안에는 스크롤뷰가 있고, 스크롤뷰는 ContentView로 구성되어 있다.
swift-scrollview-programmatically
  • 그래서 여느 스크롤뷰와 마찬가지로 ContentView에 원하는 뷰를 추가하면 될 것만 같았다.
  • 문제는 WebView안의 스크롤뷰에 뷰를 추가하면 예상과 다르게 작동한다는 것이었다.
  • WebView안에 추가한 뷰의 터치 이벤트가 작동하지 않는다.
  • WebView 안의 컴포넌트는 애플에 의해 관리되기 때문에 우리가 컨트롤하기 힘들다.
  • 그래서 웹뷰 스크롤뷰 최하단에 뷰를 추가하고 싶었는데 이를 이렇게는 구현하기 어려웠다.
  • 결국, 추가하고 싶은 LastPageView라는 뷰를 WebView와 같은 계층에 추가하고 스크롤에 대해서 속임수를 썼다.
swift-scrollview-programmatically
  • WebView의 스크롤뷰가 스크롤 될 때마다 호출되는 scrollViewDidScroll 델레게이트에 다음과 같은 코드를 작성한다.
  • 추가한 코드는 추가한 LastPageView 뷰의 y 좌표를 스크롤뷰의 포지션에 맞게 변경하는 것이다.
  • 이러면 마치 스크롤뷰 최하단에 추가한 뷰가 있는 것처럼 보이게 된다.
func scrollViewDidScroll(_ scrollView: UIScrollView) {
  positionY = scrollView.contentSize.height - scrollView.contentOffset.y - view.frame.height
  lastPageViewController?.view.frame.origin.y = positionY
}