Skip to content

SavedAppDetailTableViewCell ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ ์ง€์—ฐ ๊ฐœ์„  ย #24

Description

@yeahg-dev

Before & After

๊ฐœ์„  ์ „ ๊ฐœ์„  ํ›„
แ„€แ…ขแ„‰แ…ฅแ†ซแ„Œแ…ฅแ†ซย  แ„€แ…ขแ„‰แ…ฅแ†ซแ„’แ…ฎ low27

๋ฌธ์ œ ์ƒํ™ฉ : Cell์— ๋ฐ์ดํ„ฐ ํ‘œ์‹œ ์ง€์—ฐ

  • cellForRowAt์—์„œ ๋„คํŠธ์›Œํฌ ๋ฐ ๋ ๋ฆ„์—์„œ CellModeld์„ ๋น„๋™๊ธฐ์ ์œผ๋กœ ๋ฐ›์•„์˜ค๋Š” Publisher๋ฅผ ๋งŒ๋“  ํ›„, cell์— bindํ•ด์ฃผ๊ณ  ์ŠคํŠธ๋ฆผ์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
  • cell์ด ๋””ํ๋˜๊ธฐ ์ง์ „์— ๋น„๋™๊ธฐ์ž‘์—…์ด ์‹œ์ž‘๋˜๋ฏ€๋กœ, cell์— ๋ฐ์ดํ„ฐ๋ฅผ ํ‘œ์‹œํ•˜๊ธฐ๊นŒ์ง€ ์ง€์—ฐ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
extension AppFolderDetailViewModel: UITableViewDataSource {
    
    func tableView(
        _ tableView: UITableView,
        numberOfRowsInSection section: Int)
    -> Int
    {
        if let savedApps,
           savedApps.isEmpty {
            showEmptyView.send(true)
        } else {
            showEmptyView.send(false)
        }
        return savedApps?.count ?? 0
    }
    
    func tableView(
        _ tableView: UITableView,
        cellForRowAt indexPath: IndexPath)
    -> UITableViewCell
    {
        let cell = tableView.dequeueReusableCell(
            withClass: SavedAppDetailTableViewCell.self,
            for: indexPath)
        guard let savedApp = savedApps?[safe: indexPath.row] else {
            return cell
        }
        
        // TODO: - Error Handling
        let cellModel = appFolderUsecase.readSavedAppDetail(of: savedApp)
            .map { savedAppDetail in
                return SavedAppDetailTableViewCellModel(savedAppDetail: savedAppDetail)
            }
            .assertNoFailure()
            .eraseToAnyPublisher()
        
        cell.bind(cellModel)
        return cell
    }

}

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ• : UITableViewDataSourcePrefetching ์‚ฌ์šฉ

  • UITableViewDataSourcePrefetching๋ฅผ ์ฑ„ํƒํ•˜์—ฌ tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) ๋ฉ”์„œ๋“œ๋‚ด์—์„œ [indexPath]์— ํ•ด๋‹นํ•˜๋Š” savedApp๋“ค์˜ cellModel์„ ๋‹ค์šด๋กœ๋“œํ•˜์—ฌ ๋ฐฐ์—ด์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
extension AppFolderDetailViewModel: UITableViewDataSourcePrefetching {
    
    func tableView(
        _ tableView: UITableView,
        prefetchRowsAt indexPaths: [IndexPath])
    {
        guard let savedApps else {
            return
        }
        Publishers.Sequence<[IndexPath], Never>(sequence: indexPaths)
            .map({ indexPath in
                return (indexPath.row, savedApps[indexPath.row])
            })
            .flatMap { (index, savedApp) -> AnyPublisher<(Int, SavedAppDetail), Error> in
                return self.appFolderUsecase.readSavedAppDetail(of: savedApp, index: index)
            }
            .map{ savedAppDetail in
                return (savedAppDetail.0, SavedAppDetailTableViewCellModel(savedAppDetail: savedAppDetail.1))
            }
            .assertNoFailure()
            .sink { [unowned self] cellModel in
                self.fetchedCellModels[cellModel.0] = cellModel.1
            }.store(in: &cancellable)
    }

}
  • tableView( _ tableView: UITableView, cellForRowAt indexPath: IndexPath)์—์„œ ๋งŒ์•ฝ prefetchํ•œ cellModel์ด ์žˆ๋‹ค๋ฉด ํ•ด๋‹น cellModel์„ ์‚ฌ์šฉํ•ด ๋ฐ”์ธ๋“œํ•˜๊ณ , ์—†๋‹ค๋ฉด ์ŠคํŠธ๋ฆผ์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
extension AppFolderDetailViewModel: UITableViewDataSource {
    
    func tableView(
        _ tableView: UITableView,
        numberOfRowsInSection section: Int)
    -> Int
    {
        if let savedApps,
           savedApps.isEmpty {
            showEmptyView.send(true)
        } else {
            showEmptyView.send(false)
        }
        return savedApps?.count ?? 0
    }
    
    func tableView(
        _ tableView: UITableView,
        cellForRowAt indexPath: IndexPath)
    -> UITableViewCell
    {
        let cell = tableView.dequeueReusableCell(
            withClass: SavedAppDetailTableViewCell.self,
            for: indexPath)
        guard let savedApp = savedApps?[safe: indexPath.row] else {
            return cell
        }
        
        if let cellModel = fetchedCellModels[indexPath.row] {
            cell.bind(cellModel)
        } else {
            let cellModel = appFolderUsecase.readSavedAppDetail(of: savedApp)
                .map { savedAppDetail in
                    return SavedAppDetailTableViewCellModel(savedAppDetail: savedAppDetail)
                }
                .assertNoFailure()
                .eraseToAnyPublisher()

            cell.bind(cellModel)
        }

        return cell
    }

}

์ถ”๊ฐ€ ๋ณด์™„์ 

prefetchRowsAt๋ฉ”์„œ๋“œ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์Šคํฌ๋กค์„ ํ•ด์•ผ ํ˜ธ์ถœ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋งจ ์ฒ˜์Œ ๋ณด์—ฌ์ง€๋Š” ์…€์€ ์—ฌ์ „ํžˆ ์ง€์—ฐ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

Metadata

Metadata

Assignees

Labels

UI/UXUI, UX๊ฐœ์„ 

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions