Move item count fetching to background task
This commit is contained in:
parent
c12b9ae879
commit
6bb292ba13
|
@ -9,7 +9,7 @@ import Foundation
|
||||||
import CoreData
|
import CoreData
|
||||||
import Persistence
|
import Persistence
|
||||||
|
|
||||||
enum ItemListType: Hashable {
|
enum ItemListType: Hashable, Equatable {
|
||||||
case unread
|
case unread
|
||||||
case all
|
case all
|
||||||
case group(Group)
|
case group(Group)
|
||||||
|
@ -52,7 +52,9 @@ enum ItemListType: Hashable {
|
||||||
case .all:
|
case .all:
|
||||||
return nil
|
return nil
|
||||||
case .group(let group):
|
case .group(let group):
|
||||||
req.predicate = NSPredicate(format: "read = NO AND feed in %@", group.feeds!)
|
// use the feed ids, because passing the NSSet of feeds into the predicate results in a multithreading violation if the request is used on a different context
|
||||||
|
let feedIDs = group.feeds!.map { ($0 as! Feed).objectID }
|
||||||
|
req.predicate = NSPredicate(format: "read = NO AND feed in %@", feedIDs)
|
||||||
case .feed(let feed):
|
case .feed(let feed):
|
||||||
req.predicate = NSPredicate(format: "read = NO AND feed = %@", feed)
|
req.predicate = NSPredicate(format: "read = NO AND feed = %@", feed)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,16 @@
|
||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
import Fervor
|
import Fervor
|
||||||
|
import Persistence
|
||||||
|
import OSLog
|
||||||
|
|
||||||
|
private let signposter = OSSignposter(subsystem: "net.shadowfacts.Reader", category: "HomeCollectionViewCell")
|
||||||
|
|
||||||
class HomeCollectionViewCell: UICollectionViewListCell {
|
class HomeCollectionViewCell: UICollectionViewListCell {
|
||||||
|
|
||||||
|
private var currentItemListType: ItemListType?
|
||||||
|
private var itemCount: Int?
|
||||||
|
|
||||||
#if !targetEnvironment(macCatalyst)
|
#if !targetEnvironment(macCatalyst)
|
||||||
override func updateConfiguration(using state: UICellConfigurationState) {
|
override func updateConfiguration(using state: UICellConfigurationState) {
|
||||||
var backgroundConfig = UIBackgroundConfiguration.listGroupedCell().updated(for: state)
|
var backgroundConfig = UIBackgroundConfiguration.listGroupedCell().updated(for: state)
|
||||||
|
@ -22,4 +29,45 @@ class HomeCollectionViewCell: UICollectionViewListCell {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
override func prepareForReuse() {
|
||||||
|
super.prepareForReuse()
|
||||||
|
itemCount = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateUI(item: ItemListType, persistentContainer: PersistentContainer) {
|
||||||
|
self.currentItemListType = item
|
||||||
|
|
||||||
|
var config = UIListContentConfiguration.valueCell()
|
||||||
|
config.text = item.title
|
||||||
|
if let itemCount {
|
||||||
|
config.secondaryText = itemCount.formatted(.number)
|
||||||
|
}
|
||||||
|
config.secondaryTextProperties.color = .tintColor
|
||||||
|
self.contentConfiguration = config
|
||||||
|
|
||||||
|
Task(priority: .userInitiated) {
|
||||||
|
let state = signposter.beginInterval("fetch count", id: signposter.makeSignpostID())
|
||||||
|
if let count = await fetchCount(item: item, in: persistentContainer),
|
||||||
|
self.currentItemListType == item {
|
||||||
|
self.itemCount = count
|
||||||
|
config.secondaryText = count.formatted(.number)
|
||||||
|
self.contentConfiguration = config
|
||||||
|
}
|
||||||
|
signposter.endInterval("fetch count", state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func fetchCount(item: ItemListType, in persistentContainer: PersistentContainer) async -> Int? {
|
||||||
|
guard let request = item.countFetchRequest else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return await withCheckedContinuation({ continuation in
|
||||||
|
let context = persistentContainer.backgroundContext
|
||||||
|
context.perform {
|
||||||
|
let count = try? context.count(for: request)
|
||||||
|
continuation.resume(returning: count)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,15 +126,8 @@ class HomeViewController: UIViewController {
|
||||||
config.text = section.title
|
config.text = section.title
|
||||||
supplementaryView.contentConfiguration = config
|
supplementaryView.contentConfiguration = config
|
||||||
}
|
}
|
||||||
let listCell = UICollectionView.CellRegistration<HomeCollectionViewCell, ItemListType> { cell, indexPath, item in
|
let listCell = UICollectionView.CellRegistration<HomeCollectionViewCell, ItemListType> { [unowned self] cell, indexPath, item in
|
||||||
var config = UIListContentConfiguration.valueCell()
|
cell.updateUI(item: item, persistentContainer: self.fervorController.persistentContainer)
|
||||||
config.text = item.title
|
|
||||||
if let req = item.countFetchRequest,
|
|
||||||
let count = try? self.fervorController.persistentContainer.viewContext.count(for: req) {
|
|
||||||
config.secondaryText = "\(count)"
|
|
||||||
config.secondaryTextProperties.color = .tintColor
|
|
||||||
}
|
|
||||||
cell.contentConfiguration = config
|
|
||||||
|
|
||||||
cell.accessories = [.disclosureIndicator()]
|
cell.accessories = [.disclosureIndicator()]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue