From e7800249af074446515f173a83fd30b46caf83e4 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Mon, 18 Jan 2021 14:50:56 -0500 Subject: [PATCH] Avoid loading cached data into memory when prefetching --- Tusker/Caching/ImageCache.swift | 30 ++++++++++++++----- Tusker/MultiThreadDictionary.swift | 8 +++++ .../NotificationsTableViewController.swift | 2 +- .../Utilities/StatusTablePrefetching.swift | 4 +-- 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/Tusker/Caching/ImageCache.swift b/Tusker/Caching/ImageCache.swift index 2fb58bde..4f0840a3 100644 --- a/Tusker/Caching/ImageCache.swift +++ b/Tusker/Caching/ImageCache.swift @@ -51,13 +51,7 @@ class ImageCache { } return nil } else { - let group = RequestGroup(url: url) { (data, image) in - if let data = data { - try? self.cache.set(key, data: data) - } - self.groups.removeValueWithoutReturning(forKey: url) - } - groups[url] = group + let group = createGroup(url: url) let request = group.addCallback(completion) group.run() return request @@ -65,6 +59,28 @@ class ImageCache { } } + func fetchIfNotCached(_ url: URL) { + // if caching is disabled, don't bother fetching since nothing will be done with the result + guard !ImageCache.disableCaching else { return } + + if !((try? cache.has(url.absoluteString)) ?? false), + !groups.contains(key: url) { + let group = createGroup(url: url) + group.run() + } + } + + private func createGroup(url: URL) -> RequestGroup { + let group = RequestGroup(url: url) { (data, image) in + if let data = data { + try? self.cache.set(url.absoluteString, data: data) + } + self.groups.removeValueWithoutReturning(forKey: url) + } + groups[url] = group + return group + } + func getData(_ url: URL) -> Data? { return try? cache.getData(url.absoluteString) } diff --git a/Tusker/MultiThreadDictionary.swift b/Tusker/MultiThreadDictionary.swift index a7622aad..f71b4b01 100644 --- a/Tusker/MultiThreadDictionary.swift +++ b/Tusker/MultiThreadDictionary.swift @@ -47,4 +47,12 @@ class MultiThreadDictionary { } return value } + + func contains(key: Key) -> Bool { + var value: Bool! + queue.sync { + value = dict.keys.contains(key) + } + return value + } } diff --git a/Tusker/Screens/Notifications/NotificationsTableViewController.swift b/Tusker/Screens/Notifications/NotificationsTableViewController.swift index e4263650..cf7f69f5 100644 --- a/Tusker/Screens/Notifications/NotificationsTableViewController.swift +++ b/Tusker/Screens/Notifications/NotificationsTableViewController.swift @@ -213,7 +213,7 @@ extension NotificationsTableViewController: UITableViewDataSourcePrefetching { func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) { for indexPath in indexPaths { for notification in item(for: indexPath).notifications { - _ = ImageCache.avatars.get(notification.account.avatar, completion: nil) + ImageCache.avatars.fetchIfNotCached(notification.account.avatar) } } } diff --git a/Tusker/Screens/Utilities/StatusTablePrefetching.swift b/Tusker/Screens/Utilities/StatusTablePrefetching.swift index dd5cf1e4..46721f99 100644 --- a/Tusker/Screens/Utilities/StatusTablePrefetching.swift +++ b/Tusker/Screens/Utilities/StatusTablePrefetching.swift @@ -21,9 +21,9 @@ extension StatusTablePrefetching { return } for status in statuses { - _ = ImageCache.avatars.get(status.account.avatar, completion: nil) + ImageCache.avatars.fetchIfNotCached(status.account.avatar) for attachment in status.attachments where attachment.kind == .image { - _ = ImageCache.attachments.get(attachment.url, completion: nil) + ImageCache.attachments.fetchIfNotCached(attachment.url) } } }