diff --git a/Mastodon/Scene/Notification/NotificationViewController.swift b/Mastodon/Scene/Notification/NotificationViewController.swift index c3ad661b7..658c5fcab 100644 --- a/Mastodon/Scene/Notification/NotificationViewController.swift +++ b/Mastodon/Scene/Notification/NotificationViewController.swift @@ -198,32 +198,34 @@ extension NotificationViewController { // MARK: - StatusTableViewControllerAspect extension NotificationViewController: StatusTableViewControllerAspect { } -// MARK: - TableViewCellHeightCacheableContainer -extension NotificationViewController: TableViewCellHeightCacheableContainer { - var cellFrameCache: NSCache { - viewModel.cellFrameCache - } +extension NotificationViewController { func cacheTableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) { guard let diffableDataSource = viewModel.diffableDataSource else { return } guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return } - let key = item.hashValue - let frame = cell.frame - viewModel.cellFrameCache.setObject(NSValue(cgRect: frame), forKey: NSNumber(value: key)) + switch item { + case .notification(let objectID, _): + guard let object = try? viewModel.fetchedResultsController.managedObjectContext.existingObject(with: objectID) as? MastodonNotification else { return } + let key = object.id as NSString + let frame = cell.frame + viewModel.cellFrameCache.setObject(NSValue(cgRect: frame), forKey: key) + case .bottomLoader: + break + } } func handleTableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { guard let diffableDataSource = viewModel.diffableDataSource else { return UITableView.automaticDimension } guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return UITableView.automaticDimension } - guard let frame = viewModel.cellFrameCache.object(forKey: NSNumber(value: item.hashValue))?.cgRectValue else { - if case .bottomLoader = item { - return TimelineLoaderTableViewCell.cellHeight - } else { - return UITableView.automaticDimension - } + switch item { + case .notification(let objectID, _): + guard let object = try? viewModel.fetchedResultsController.managedObjectContext.existingObject(with: objectID) as? MastodonNotification else { return UITableView.automaticDimension } + let key = object.id as NSString + guard let frame = viewModel.cellFrameCache.object(forKey: key)?.cgRectValue else { return UITableView.automaticDimension } + return frame.height + case .bottomLoader: + return TimelineLoaderTableViewCell.cellHeight } - - return ceil(frame.height) } } @@ -237,6 +239,14 @@ extension NotificationViewController: UITableViewDelegate { open(item: item) } + func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) { + cacheTableView(tableView, didEndDisplaying: cell, forRowAt: indexPath) + } + + func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { + return handleTableView(tableView, estimatedHeightForRowAt: indexPath) + } + } extension NotificationViewController { diff --git a/Mastodon/Scene/Notification/NotificationViewModel.swift b/Mastodon/Scene/Notification/NotificationViewModel.swift index 34f99d59f..4c3b975cf 100644 --- a/Mastodon/Scene/Notification/NotificationViewModel.swift +++ b/Mastodon/Scene/Notification/NotificationViewModel.swift @@ -29,7 +29,7 @@ final class NotificationViewModel: NSObject { let activeMastodonAuthenticationBox: CurrentValueSubject let fetchedResultsController: NSFetchedResultsController! let notificationPredicate = CurrentValueSubject(nil) - let cellFrameCache = NSCache() + let cellFrameCache = NSCache() var needsScrollToTopAfterDataSourceUpdate = false let dataSourceDidUpdated = PassthroughSubject()