-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
UI/UXUI, UX개선UI, UX개선
Description
Before & After
| 개선 전 | 개선 후 |
|---|---|
|
![]() |
문제 상황 : 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메서드는 사용자가 스크롤을 해야 호출되기 때문에 맨 처음 보여지는 셀은 여전히 지연이 발생합니다.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
UI/UXUI, UX개선UI, UX개선

