๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐Ÿงฏ Troubleshooting

[Cheliz] Pagination (+ API ํ†ต์‹ )

 

  ๋ฌธ์ œ  

 

์ž‘ํ’ˆ ๊ฒ€์ƒ‰ ํ™”๋ฉด์—์„œ Pagination์„ ์œ„ํ•ด, UIScrollViewDelegate Protocol์„ ์‚ฌ์šฉํ•˜์—ฌ scrollView์˜ offset์„ ํ™œ์šฉํ•ด ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ์ถ”๊ฐ€ ๋กœ๋”ฉ์„ ๊ตฌํ˜„ํ•˜์˜€๋‹ค.

offset.y๊ฐ€ scrollView.contentSize.height (== searchView.collectionView.contentSize.height)์˜ 67% ์ด์ƒ์ด ๋  ๋•Œ, ๋งˆ์ง€๋ง‰์œผ๋กœ ๋กœ๋”ฉํ•œ ํŽ˜์ด์ง€๊ฐ€ ์ด ํŽ˜์ด์ง€ ์ˆ˜๋ณด๋‹ค ์ ์„ ๊ฒฝ์šฐ ๋‹ค์Œ ํŽ˜์ด์ง€๋ฅผ API ํ†ต์‹ ์„ ํ†ตํ•ด ๋ฐ›์•„ ์˜ค๋Š” ๋กœ์ง์œผ๋กœ ๊ตฌ์„ฑํ•˜์˜€๋‹ค.

 

func scrollViewDidScroll(_ scrollView: UIScrollView) {
        isPaginating = true

        let contentOffset = scrollView.contentOffset.y
        let collectionViewHeight = searchView.collectionView.contentSize.height
        let remainingHeight = collectionViewHeight * 0.33

        // contentSize.height์€ ์™œ์ธ์ง€ ๋„ˆ๋ฌด ์ปค์„œ(2553.6) remainingHeight์ด collectionViewHeight์˜ 20%์ผ ๋•Œ๋Š” ๋”์ด์ƒ ๋กœ๋”ฉ์ด ์•ˆ ๋จ.

        print("๐Ÿ‹ contentOffset: \\(contentOffset)")
        print("๐Ÿ’ collectionViewHeight: \\(collectionViewHeight)")  // 2553.6
        print("๐Ÿซ remainingHeight: \\(remainingHeight)")  // 1021.44
        print("๐Ÿ’ - ๐Ÿซ: \\(collectionViewHeight - remainingHeight)")
//        print(page < totalPages)
        print("๐Ÿ“ƒ page: \\(page)")

        if contentOffset > collectionViewHeight - remainingHeight && page < totalPages {
            page += 1
            search()
        }
    }

 

์ผ๋‹จ, ๋‹ค์Œ ํŽ˜์ด์ง€๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•˜๊ธด ํ•˜๋‹ค..

ํ•˜์ง€๋งŒ scrollViewDidScroll ๋ฉ”์„œ๋“œ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์Šคํฌ๋กค์„ ํ•  ๋•Œ๋งˆ๋‹ค ํ˜ธ์ถœ๋˜๊ณ , ์†๊ฐ€๋ฝ์ด ํ™”๋ฉด์„ ํ„ฐ์น˜ํ•˜๊ณ  ๋—„ ๋•Œ ํ•œ ๋ฒˆ ํ˜ธ์ถœ๋˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ offset์ด ์กฐ๊ธˆ์ด๋ผ๋„ ๋ฐ”๋€Œ๋ฉด ํ˜ธ์ถœ๋˜๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์—ˆ๋‹ค..

 

API ํ†ต์‹  ํ›„ response๊ฐ€ ์˜ค๊ณ  ๋‚˜์„œ์•ผ collectionView๊ฐ€ ์—…๋ฐ์ดํŠธ ๋˜๋ฉด์„œ contentSize.height(์ดํ•˜ ์ปฌ๋ ‰์…˜ ๋ทฐ ๋†’์ด)๊ฐ€ ๋ฐ”๋€Œ๋Š”๋ฐ, ๋ณดํ†ต ๊ทธ ์ „์— ์Šคํฌ๋กค์ด ๊ณ„์† ์ด๋ฃจ์–ด์ง€๋ฏ€๋กœ ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋Š” ๊ณ„์† ํ˜ธ์ถœ์ด ๋˜๊ณ , ์ด ๋•Œ offset.y๋Š” ์—…๋ฐ์ดํŠธ ๋˜๊ธฐ ์ „์˜ ์ปฌ๋ ‰์…˜ ๋ทฐ ๋†’์ด์˜ 67% ์ด์ƒ์ด๋ฏ€๋กœ ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ๋งˆ๋‹ค API ํ†ต์‹ ์ด ์ผ์–ด๋‚˜๊ฒŒ ๋˜์–ด ๊ณผํ˜ธ์ถœ์ด ๋ฐœ์ƒํ•œ๋‹ค.

 

์ด๋Š” ์•„์ดํฐ ํ™”๋ฉด์—์„œ ์Šคํฌ๋กค๋ฐ”์˜ ์œ„์น˜๋ฅผ ํ†ตํ•ด ์‹œ๊ฐ์ ์œผ๋กœ๋„ ํ™•์ธ์ด ๊ฐ€๋Šฅํ•œ๋ฐ, ์ฒซ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ํ‘œ์‹œ ํ™”๋ฉด์—์„œ ์Šคํฌ๋กค์„ ํ•ด์„œ ๋‹ค์Œ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•˜๋ ค ํ•˜๋ฉด, ์Šคํฌ๋กค์ด ์ž‘์•„์ง€๊ณ  ์Šคํฌ๋กค๋ฐ”๊ฐ€ ์—„์ฒญ๋‚œ ์ƒ๋‹จ..;;์œผ๋กœ ์ด๋™ํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์Šคํฌ๋กค๋ฐ”๊ฐ€ ์ด๋™ํ•  ๋•Œ๋„ ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ์›€์ง์ด๊ธฐ๋ณด๋‹ค ๋š๋š ๋Š๊ฒจ (choppy) ๋ณด์ธ๋‹ค. (์œ„๋กœ ์—„์ฒญ๋‚˜๊ฒŒ ์ ํ”„ํ•˜๋‹ˆ๊นŒใ… )

 

๊ณผํ˜ธ์ถœ๋กœ ์ธํ•ด ๊ณผ๋‹คํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ฒŒ ๋˜๊ณ , ์ด ๊ณผ๋‹คํ•œ ๋ฐ์ดํ„ฐ๋ฅผ UI๋กœ ๋ณด์—ฌ์ฃผ์–ด์•ผ ํ•˜๋Š” Main Thread๊ฐ€ ํ•  ์ผ์ด ๋งŽ์•„ ๋ง‰ํžˆ๋Š” ๊ฒƒ์ด๋‹ค.. ใ…  ๊ฒฐ๊ตญ ๋งค๋„๋Ÿฝ์ง€ ๋ชปํ•˜๊ณ  ๋Š๊ฒจ ๋ณด์ด๊ฒŒ ๋˜์–ด ์‚ฌ์šฉ์ž๊ฐ€ ๋ณด๊ธฐ์—๋„ ์‚ฌ์šฉ์„ฑ์ด ๋–จ์–ด์ง€๊ฒŒ ๋œ๋‹ค...ใ… .ใ… 

 

๋˜ํ•œ ์ด๋Š” API ๊ณผํ˜ธ์ถœ๋กœ ์ธํ•œ ์„œ๋ฒ„๋‹จ์˜ ํด๋ผ์ด์–ธํŠธ block์„ ์ดˆ๋ž˜ํ•  ์ˆ˜ ์žˆ๋‹ค.. ์œ ์ €์˜ ์…€๋ฃฐ๋Ÿฌ/์™€์ดํŒŒ์ด ๊ณผ๋‹ค ์‚ฌ์šฉ์€ ๋ค..

 

 

  ํ•ด๊ฒฐ  

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด pagination ๋ฐฉ๋ฒ•์„ ๋ณ€๊ฒฝํ–ˆ๋‹ค..! 

UICollectionViewDataSourcePrefetching protocol์„ ์‚ฌ์šฉํ•˜์˜€๋‹ค. prefetching์„ ํ†ตํ•ด ์…€์„ ํ™”๋ฉด์— ํ‘œ์‹œํ•˜๊ธฐ ์ „ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฏธ๋ฆฌ ์š”์ฒญํ•  ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ๋‹ค.

extension SearchViewController: UICollectionViewDataSourcePrefetching {
    func collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath]) {
        for indexPath in indexPaths {  // indexPaths: prefetch๋˜๋Š” ์…€๋“ค
            if searchResults.count - 1 == indexPath.item && page < totalPages {
                isPaginating = true
                page += 1
                search()
            }
        }
    }
}

prefetch ๋˜๋Š” ์…€๋“ค ์ค‘ ์ด๋ฏธ ๋ถˆ๋Ÿฌ์˜จ ๊ฒ€์ƒ‰๊ฒฐ๊ณผ์˜ ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰์— ํ•ด๋‹นํ•˜๋Š” ์…€์—์„œ ๋‹ค์Œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฏธ๋ฆฌ ๋ฐ›์•„์˜ค๋„๋ก ๊ตฌํ˜„ํ•˜์˜€๊ณ , ์ด๋ ‡๊ฒŒ ํ™”๋ฉด์— ๋ณด์ด๊ธฐ ์ „ ๋ฏธ๋ฆฌ ๋กœ๋”ฉ๋œ ๋ฐ์ดํ„ฐ๋Š” UICollectionViewDataSource ํ”„๋กœํ† ์ฝœ์˜ cellForItemAt ๋ฉ”์„œ๋“œ์—์„œ ํ™”๋ฉด์— ํ‘œ์‹œ๋œ๋‹ค.

 

UICollectionViewDataSourcePrefetching protocol์„ ์‚ฌ์šฉํ•˜๋ฉด ์Šคํฌ๋กค ์„ฑ๋Šฅ๋„ ํ–ฅ์ƒ๋œ๋‹ค๊ณ  ํ•œ๋‹ค! ๊ทธ๊ฒƒ์ด ์Šคํฌ๋กค๋ฐ”์˜ ๋งค๋„๋Ÿฌ์šด ์ด๋™์„ ๋œปํ•˜๋Š” ๊ฑด์ง€๋Š” ์ •ํ™•ํ•˜๊ฒŒ ๋ชจ๋ฅด๊ฒ ์ง€๋งŒ,.. ์œ ์ €๋กœ์„œ ๋ณด๊ธฐ์—๋Š” ์ด์ „๋ณด๋‹ค ํ›จ์”ฌ smoothํ•œ ์Šคํฌ๋กค๋ฐ”๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์—ˆ๋‹ค..! (๋„ค์ด๋ฒ„ ๊ฒ€์ƒ‰์ฒ˜๋Ÿผ..)

 

 

 

 

์ฐธ๊ณ 

Apple Developer Documentation - UICollectionViewDataSourcePrefetching

Apple Developer Documentation - Prefetching Collection View Data

 

Apple Developer Documentation

 

developer.apple.com

Kodeco - UICollectionView Tutorial: Prefetching APIs

 

UICollectionView Tutorial: Prefetching APIs

In this UICollectionView prefetching tutorial, you’ll learn how to achieve smooth scrolling in your app using Operations and Prefetch APIs.

www.kodeco.com