본문 바로가기

TIL

[TIL] TikTok 피드 구현 과정

소개

본격적인 프로젝트에 들어가기 앞서 이번에 TikTok 피드처럼 UI를 구성하기 위해 따로 프로젝트를 만들어 미리 테스트 해본 과정을 소개하는 내용입니다.

 

참고 강의

TikTok UI 에 대한 자료는 아래 강의를 기반으로 진행하였습니다.

https://www.youtube.com/watch?v=j1w6Ed5-3tA

 

구현 과정

위 강의 구현한 TikTok 피트 UI는 CollectionView를 이용하였습니다. 이는 CollectionView의 Cell이 TableView Cell보다 Size를 CollectionView Layout 설정을 통해 좀 더 명시적으로 지정해줄 수 있기 때문이라고 생각됩니다.

 

따라서 기본적으로 CollectionView를 구성해줍니다. 

 

아래 코드는 Collection View를 기본적으로 구성해주는 코드입니다.

 lazy var collectionView: UICollectionView = {
        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: createCollectionViewLayout())
        collectionView.isPagingEnabled = true // Collection View 페이지 스크롤 켜기
        collectionView.dataSource = self
        
        collectionView.register(TikTokFeedCollectionViewCell.self, forCellWithReuseIdentifier: TikTokFeedCollectionViewCell.identifier)
        
        return collectionView
    }()

위 코드에서 신경써주어야 할 부분은 TikTok 피드는 기본적으로 세로로 페이지 단위로 스크롤되기 때문에 isPagingEnabled의 값을 true로 지정해주어야 한다.

 

다음 코드는 CollectionView의 Layout를 설정해주는 코드입니다.

 private func createCollectionViewLayout() -> UICollectionViewLayout {
        
        let layout = UICollectionViewFlowLayout()
        
        let topSafeareInset = getSafeareInset().top // 상태바 높이
        let tabBarHeight = tabBarController?.tabBar.frame.height ?? 0 // 탭바 높이
        layout.scrollDirection = .vertical
        layout.itemSize = CGSize(width: view.frame.size.width,
                                 height: view.frame.size.height - (topSafeareInset + tabBarHeight)) // 상태바 높이 + 탭바 높이 만큼 빼주기
        layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
        
        layout.minimumLineSpacing = 0 // 셀간 간격 없애기
                
        return layout
    }

 

위 코드에서 좀 더 신경써주어야 할 부분이 등장하는데요.

그 부분은 바로 Collection View의 itemSize를 지정하는 부분입니다. 

왜냐하면 itemSize의 높이를 지정해줄 때 상태바의 높이와 탭 바 높이만큼 빼어주야 제대로된 화면의 크기(SafeArea의 크기)가 계산될 수 있기 때문입니다. 

 

여기에 Collection View에서 Cell간의 수직 간이 기본적으로 10이 설정되어 있기 때문에 이 설정도 0으로 수정해주어야 화면에서 제대로 보입니다.

 

다음은 설정 후 화면입니다.

 

추가적으로 getSafeareInset() 메서드는 다음과 같이 구성하였습니다.

private func getSafeareInset() -> UIEdgeInsets {
        // connectedScenes에 접근하여 첫번째 scene 가져오기
        let connectedScene = UIApplication.shared.connectedScenes.first
        
        // UIWindowScene으로 캐스팅
        let windowScene = connectedScene as? UIWindowScene
        
        // 첫번째 window 가져오기
        let window = windowScene?.windows.first
        
        // safeAreaInset 획득
        let safeAreaInset = window?.safeAreaInsets ?? .zero
        return safeAreaInset
    }

 

여기에 각 Cell마다 눈에 잘 띠게 이미지를 표시해보겠습니다.

다음은 완성된 실행화면입니다.

 

생각보다 잘 동작하는 것 같습니다. 

 

이제 여기에 제가 원하는 화면만 그려주면 될 것 같습니다.

 

글 읽어주셔서 정말 감사합니다!

 

추가사항!!!(4월 13일 적용 이후)

발생한 문제점

아래 화면을 보시면 TabBar추가를 추가하고, 피드 화면 적용 후 화면에서 화면 하단에 1~2px정도 차이 나는 것을 확인해 보실 수 있습니다.

처음엔 무엇이 원인인지 불명확했는데 알고보니 iPhone 14 Pro부터 도입된 Dynamic Island로 인해 해상도 차이가 났던 것입니다.

 

해결방법

해결방법은 의외로 간단했습니다. 바로 Modern Collection View의 Compositional Layout을 구성하여 Collection View의 레이아웃을 잡아주면 되는 것이었습니다.

 

아래 코드를 보니 비교적 코드도 더 간결하고, 읽기 쉬운 것 같습니다.

func createCollectionViewLayout() -> UICollectionViewLayout {
    let itemSize = NSCollectionLayoutSize(
        widthDimension: .fractionalWidth(1.0),
        heightDimension: .fractionalHeight(1.0)
    )
    let item = NSCollectionLayoutItem(layoutSize: itemSize)

    let groupSize = NSCollectionLayoutSize(
        widthDimension: .fractionalWidth(1.0),
        heightDimension: .fractionalHeight(1.0)
    )
    let group = NSCollectionLayoutGroup.horizontal(
        layoutSize: groupSize,
        subitems: [item]
    )

    let section = NSCollectionLayoutSection(group: group)

    return UICollectionViewCompositionalLayout(section: section)
}

 

오류 수정 참고 사이트

https://gyuios.tistory.com/262 (Dynamic Island 도입에 따른 스크린 사이즈 변화 설명)

'TIL' 카테고리의 다른 글

[TIL] Swift Concurrency 등장 배경  (0) 2024.05.08
[TIL] Alamofire을 이용한 Token 갱신 적용  (0) 2024.05.04
[TIL] Single에 대한 간단 내용 정리  (0) 2024.04.08
[TIL] 스트림 공유  (1) 2024.04.05
[TIL] RxSwift 간단 요약 정리  (0) 2024.04.03