ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • UITableView와 UICollectionView의 AutoSize에 관하여..
    앱등이에게 살충제를 뿌린다./일기는 일기장에 2017. 6. 17. 17:54

    작업메모라서 사진은 첨부안했습니다.

    관련 이슈 있으신분은 댓글로 달아주세요~ 아는범위에서 답 드릴게요 :)


    UITableView와 UICollectionView의 Auto size cell..


    https://theswiftdev.com/2016/08/08/self-sizing-cells-with-rotation-support-in-swift-3/

    위 사이트에 굉장히 잘 정리되어 있음


    이 Auto Sizing Cell의 컨셉과 사용법은 굉장히 간단하다.

    Cell의 오토레이아웃을 기반으로 알아서 셀의 사이즈가 결정된다. 개발자가 코드로 계산할 필요가 없이 Dynamic하게 결정되는 것이다.


    방법도 굉장히 간단하다.


    tableView.estimatedRowHeight = 44

    tableView.rowHeight = UITableViewAutomaticDimension


    진짜 완전 초 간단..


    그런데 큰 문제점이 있다.


    1. 테이블뷰는 괜찮은데 컬렉션뷰에서 큰 문제 큰 문제가 있다.

    UICollectionViewController에 달려있는 CollectionView에서는 잘 되는 셀프사이징이 UIViewController에 올린 UICollectionView에서는 오동작하는 경우가 많다.

    팀쿡 뚝배기 깨고싶다


    2. UIScrollView의 contentSize가 실제 셀 사이즈가 아닌 estimated사이즈의 합으로 계산된다.

    이걸로 페더리히 뚝배기 깨고싶다.





    2번의 경우가 문제되었던 경우는 이렇다.

    무한 스크롤을 지원하는 UITableView를 작업중이고, 스크롤이 끝에 도달할 때까지 model업데이트가 안되어 있다면 마지막셀의 아래에 loading Indicator를 보여주어야 한다.

    과정은 아래와 같다.


    1. API호출이 시작되면 tableView의 하단에 inset을 추가하고 해당 inset영역에 loadingView를 addSubview해준다.

    2. API호출이 끝나면 tableView의 하단 inset을 제거하고 loadingView를 removeFromSuperview한다.


    이제부터 문제가 발생한다.

    addSubview를 할 때, 오토레이아웃으로 tableView.bottom == loadingView.bottom하면, loadingView가 테이블뷰 바닥에 붙어야 할 것 같은데, 최상단에 붙는다.


    tableView.top == loadingView.top

    tableView.left == loadingView.left 이 두가지의 constraint는 기대하는 대로 작동하지만


    tableView.right == loadingView.right는 loadingView가 left에 붙고

    tableView.bottom == loadingView.bottom는 loadingView가 top에 붙는 기이한 현상이 생긴다.


    이는 UIScrollView와 Auto Layout관계에서 발생하는.. 그러한 이슈다.


    그래서 난 tableView.top == loadingView.top를 한 뒤에 constant = tableView.contentSIze를 적용하였다.

    얼마나 깔끔한가? top에서 contentSize만큼 내리면 결국 bottom에 붙을테니,,

    이 모든 코드를 공통화하여 UIScrollView의 extension에 추가했다.


    대부분의 TableView, CollectionView에서 잘 작동했다.

    하지만 Auto size를 사용하는 TableView에서 뒷통수를 맞았다.

    contentSize가 실제 contentSize가 아닌 estimated row height의 합산으로 리턴이 되었다.

    여기서 워즈니악 뚝배기 깨고싶다.


    하지만 우리 사장님의 뚝배기는 지켜드려야 하기 때문에 방법을 떠올리다 이렇게 결론냈다.


    loadingView가 나타나는 시점은 API를 호출하는 시점이 아니다. willDisplayCell에서 마지막 cell이 나타나기전 api를 요청중이라면 그 때 loadingView를 나타낸다.

    Auto size를 사용하더라도 willDisplayCell에서 마지막 cell의 cell.frame.maxY를 사용하면 정확한 contentSize를 알 수 있기 때문이다.




    수고했으니 배주현님 감상하시고 린멘





Designed by Tistory.