We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cellForRowAt
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
tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath])
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)
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메서드는 사용자가 스크롤을 해야 호출되기 때문에 맨 처음 보여지는 셀은 여전히 지연이 발생합니다.
prefetchRowsAt
The text was updated successfully, but these errors were encountered:
👍REFACTOR: UITableViewDataSourcePrefetching로 데이터 지연 개선 #24
d7e37e5
yeahg-dev
No branches or pull requests
Before & After
문제 상황 : Cell에 데이터 표시 지연
cellForRowAt
에서 네트워크 및 렐름에서 CellModeld을 비동기적으로 받아오는 Publisher를 만든 후, cell에 bind해주고 스트림을 시작합니다.해결 방법 :
UITableViewDataSourcePrefetching
사용UITableViewDataSourcePrefetching
를 채택하여tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath])
메서드내에서 [indexPath]에 해당하는 savedApp들의 cellModel을 다운로드하여 배열에 저장합니다.tableView( _ tableView: UITableView, cellForRowAt indexPath: IndexPath)
에서 만약 prefetch한 cellModel이 있다면 해당 cellModel을 사용해 바인드하고, 없다면 스트림을 시작합니다.추가 보완점
prefetchRowsAt
메서드는 사용자가 스크롤을 해야 호출되기 때문에 맨 처음 보여지는 셀은 여전히 지연이 발생합니다.The text was updated successfully, but these errors were encountered: