본문 바로가기
iOS

[iOS] UITableView Scroll issue에 대해 - pointee 활용법

by 코딩친구 2022. 9. 27.
반응형

테이블뷰 인스타그램 검색 화면 애니메이션

 

 

 

 

func scrollViewWillEndDragging 를 이용해 구현하였다.

 

pointee를 이용해 내가 가리키고 있는 y축이 게시물의 절반을 넘어갈 때

화면이 밑으로 이동해 화면 맨 위에 cell의 top이 딱 걸리도록 하는

마치 인스타그램 검색 화면과 같이 딱딱 넘어가는 테이블 뷰를 만들고 싶은 게 목적!

 

 

기본적으로

 

        imageTableView.decelerationRate = .fast
        imageTableView.contentInsetAdjustmentBehavior = .never

 

TableView의 스크롤 속도를 높이고,

ScrollView의 Content 영역에 Safe Area Insets을  never로 주어 inset을 없애고 시작하였다.

 

 

 

    func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        
        // 내가 가리키고 있는 y축 : 빨리 스크롤을 하면 더 많이 가서 도착할 지점, 적게 스크롤을 하면 적게 가서 도착할 지점
        let num = Int(targetContentOffset.pointee.y)

        var targetOffsetY = CGFloat(num + (540 - num % 540))

        if num % 540 >= 270 {
            
        } else {
            targetOffsetY = CGFloat(num - num % 540)
        }

        targetContentOffset.pointee.y = targetOffsetY
    }

 

targetContentOffset을 이용하여 구현할 수 있다.

 

tableviewcell의 높이를 540으로 고정해두었기 때문에

내가 밑 방향으로 스크롤을 해서 놓았을 때 멈추는 지점이

 

270보다 크면

그대로 흘러가서 다음 cell의 위에 걸치고,

아니면

다시 내 cell의 위에 걸치게 targetOffsetY를 계산하여 적용하였다.

 

 

targetContentOffset.pointee.y는 내가 스크롤을 했을 때 멈출 y좌표를 뜻한다!

내가 가리키고 있는 y축 : 빨리 스크롤을 하면 더 많이 가서 도착할 지점, 적게 스크롤을 하면 적게 가서 도착할 지점

 

 

 

구현 완료한 모습

 

 

 

 

하지만 맨 첫 번째 셀부터 알 수 있듯이,

틱틱거리는 현상이 나타난다!

 

 

역방향의 애니메이션은 구현되어있지 않기 때문.

 

 

무슨 말이냐,

 

-> 내가 스크롤해서 내린 방향과 도달해야하는 방향이 다른 경우

-> 너무 작게 올리거나 작게 내린 경우

-> 다시 원래 게시물로 돌아와야하는 경우!

 

 

 

이를 방지하는 방법은 코드로 설명하겠다.

 

 

    func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        
        // 내가 가리키고 있는 y축 : 빨리 스크롤을 하면 더 많이 가서 도착할 지점, 적게 스크롤을 하면 적게 가서 도착할 지점
        let num = Int(targetContentOffset.pointee.y)

        var targetOffsetY = CGFloat(num + (540 - num % 540))

        if num % 540 >= 270 {
            
        } else {
            targetOffsetY = CGFloat(num - num % 540)
        }
        
        if scrollView.contentOffset.y < targetContentOffset.pointee.y {
            // 아래로 내려가는 경우
            if targetOffsetY > scrollView.contentOffset.y {
                // 방향이 같음
                // 내가 가야할 마지막 목적지로 pointee를 설정해준다.
                targetContentOffset.pointee.y = targetOffsetY
            } else {
                // 방향이 다름
                // 스크롤이 끝나자마자의 y축을 지금 가리키는 y축으로 만들어버린다 -> 스크롤 끝나자마자 멈추는 것처럼 마치 띡하고 멈춰버림
                targetContentOffset.pointee.y = scrollView.contentOffset.y
                // 그리고 나서 내가 향할 방향으로 animation을 줘서 물흐르듯 다시 만들어준다.
                scrollView.setContentOffset(.init(x: 0, y: targetOffsetY), animated: true)
            }
        } else {
            // 올라가는 경우
            if targetOffsetY > scrollView.contentOffset.y {
                // 방향이 다름
                targetContentOffset.pointee.y = scrollView.contentOffset.y
                scrollView.setContentOffset(.init(x: 0, y: targetOffsetY), animated: true)
            } else {
                // 방향이 같음
                targetContentOffset.pointee.y = targetOffsetY
            }
        }
    }

 

 

1. 스크롤을 내릴 때

 1) 조금 내려서 다시 돌아와야하는 경우 (역방향)

 2) 많이 내려서 다음 게시물로 넘어가는 경우 (정방향)

 

2. 스크롤을 올릴 때

 1) 조금 올려서 다시 돌아와야하는 경우 (역방향)

 2) 많이 올려서 이전 게시물로 넘어가는 경우 (정방향)

 

 

 

역방향일 경우 스크롤을 멈추게하고, 반대방향까지 animation을 주어 물흐르듯 만들어주면 이런 버그가 해결된다....!

 

이 버그는 Apple OS적 에러라, UI를 세세하게 신경써야하는 앱이라면 이런 부분까지 생각하며 구현하면 좋다.

아직 이런 내용은 찾아도 많이 나오지 않아 글로 남기게 되었다.

 

 

 

 

부드럽게 구현 완료한 모습

 

반응형