Create and use IconImageCache. It centralizes and de-dupes logic for getting feed/article images, and it caches the results, which helps performance.

This commit is contained in:
Brent Simmons
2021-05-08 12:42:44 -07:00
parent 28b00260e0
commit 9d2c8f000f
12 changed files with 160 additions and 174 deletions

View File

@@ -132,6 +132,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
func applicationWillTerminate(_ application: UIApplication) {
shuttingDown = true
}
func applicationDidEnterBackground(_ application: UIApplication) {
IconImageCache.shared.emptyCache()
}
// MARK: Notifications

View File

@@ -23,14 +23,8 @@ class WebFeedInspectorViewController: UITableViewController {
@IBOutlet weak var feedURLLabel: InteractiveLabel!
private var headerView: InspectorIconHeaderView?
private var iconImage: IconImage {
if let feedIcon = appDelegate.webFeedIconDownloader.icon(for: webFeed) {
return feedIcon
}
if let favicon = appDelegate.faviconDownloader.faviconAsIcon(for: webFeed) {
return favicon
}
return FaviconGenerator.favicon(webFeed)
private var iconImage: IconImage? {
return IconImageCache.shared.imageForFeed(webFeed)
}
private let homePageIndexPath = IndexPath(row: 0, section: 1)

View File

@@ -42,11 +42,6 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner {
return true
}
private var smartFeedIconImageCache = [FeedIdentifier: IconImage]()
private var webFeedIconImageCache = [FeedIdentifier: IconImage]()
private var faviconImageCache = [FeedIdentifier: IconImage]()
private var smallIconImageCache = [FeedIdentifier: IconImage]()
override func viewDidLoad() {
super.viewDidLoad()
@@ -91,12 +86,7 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner {
}
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
// Empty IconImage caches
smartFeedIconImageCache = [FeedIdentifier: IconImage]()
webFeedIconImageCache = [FeedIdentifier: IconImage]()
faviconImageCache = [FeedIdentifier: IconImage]()
smallIconImageCache = [FeedIdentifier: IconImage]()
IconImageCache.shared.emptyCache()
super.traitCollectionDidChange(previousTraitCollection)
reloadAllVisibleCells()
}
@@ -858,69 +848,12 @@ private extension MasterFeedViewController {
}
func configureIcon(_ cell: MasterFeedTableViewCell, _ identifier: MasterFeedTableViewIdentifier) {
cell.iconImage = imageFor(identifier)
guard let feedID = identifier.feedID else {
return
}
cell.iconImage = IconImageCache.shared.imageFor(feedID)
}
func imageFor(_ identifier: MasterFeedTableViewIdentifier) -> IconImage? {
guard let feedID = identifier.feedID else { return nil }
if let smartFeed = SmartFeedsController.shared.find(by: feedID) {
return imageForSmartFeed(smartFeed, feedID)
}
guard let feed = AccountManager.shared.existingFeed(with: feedID) else { return nil }
if let webFeed = feed as? WebFeed, let iconImage = imageForWebFeed(webFeed, feedID) {
return iconImage
}
if let smallIconProvider = feed as? SmallIconProvider, let iconImage = imageForSmallIconProvider(smallIconProvider, feedID) {
return iconImage
}
return nil
}
func imageForSmartFeed(_ smartFeed: PseudoFeed, _ feedID: FeedIdentifier) -> IconImage? {
if let iconImage = smartFeedIconImageCache[feedID] {
return iconImage
}
if let iconImage = smartFeed.smallIcon {
smartFeedIconImageCache[feedID] = iconImage
return iconImage
}
return nil
}
func imageForWebFeed(_ webFeed: WebFeed, _ feedID: FeedIdentifier) -> IconImage? {
if let iconImage = webFeedIconImageCache[feedID] {
return iconImage
}
if let iconImage = appDelegate.webFeedIconDownloader.icon(for: webFeed) {
webFeedIconImageCache[feedID] = iconImage
return iconImage
}
if let faviconImage = faviconImageCache[feedID] {
return faviconImage
}
if let faviconImage = appDelegate.faviconDownloader.faviconAsIcon(for: webFeed) {
faviconImageCache[feedID] = faviconImage
return faviconImage
}
return nil
}
func imageForSmallIconProvider(_ provider: SmallIconProvider, _ feedID: FeedIdentifier) -> IconImage? {
if let iconImage = smallIconImageCache[feedID] {
return iconImage
}
if let iconImage = provider.smallIcon {
smallIconImageCache[feedID] = iconImage
return iconImage
}
return nil
}
func nameFor(_ node: Node) -> String {
if let displayNameProvider = node.representedObject as? DisplayNameProvider {
return displayNameProvider.nameForDisplay

View File

@@ -146,22 +146,12 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider {
// At some point we should refactor the current Feed IndexPath out and only use the timeline feed
private(set) var currentFeedIndexPath: IndexPath?
var timelineIconImage: IconImage? {
if let feed = timelineFeed as? WebFeed {
let feedIconImage = appDelegate.webFeedIconDownloader.icon(for: feed)
if feedIconImage != nil {
return feedIconImage
}
if let faviconIconImage = appDelegate.faviconDownloader.faviconAsIcon(for: feed) {
return faviconIconImage
}
guard let timelineFeed = timelineFeed else {
return nil
}
return (timelineFeed as? SmallIconProvider)?.smallIcon
return IconImageCache.shared.imageForFeed(timelineFeed)
}
private var exceptionArticleFetcher: ArticleFetcher?