Skip to content

Commit 72ad00b

Browse files
committed
FetchImage 0.6.0
1 parent 1994159 commit 72ad00b

File tree

6 files changed

+281
-61
lines changed

6 files changed

+281
-61
lines changed

CHANGELOG.md

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,33 @@
11
# FetchImage 0.x
22

3+
## FetchImage 0.6.0
4+
5+
*April 17, 2021*
6+
7+
- Added `ScrollViewPrefetcher` which can be accessed via a `PrefetchImageModel` object. This helps prefetch images when using SwiftUI collections.
8+
- Updated to Nuke 9.5
9+
- Updated to Firebase 7.10
10+
- Added background loading for Firebase URLs
11+
- `@Publishable` updates are now all on the main thread
12+
13+
314
## FetchImage 0.5.0
415

5-
*Mar 16, 2021*
16+
*March 16, 2021*
617

718
- The Firebase `load` call now provides a URL once cached.
819

920
## FetchImage 0.4.0
1021

11-
*Mar 03, 2021*
22+
*March 03, 2021*
1223

1324
- **Internal Change** `ImageRequest` objects are now optional and may not be immediately fulfilled when initializing a `FetchImage` instance. This allows expansion of the API for additional changes and improvements.
1425
- Google Firebase support. Using the new convenience initializer to create a `FetchImage` instance with a Firestore `StorageReference` instead of directly from a URL. Optionally, supply any cached URL content when using this initializer to decrease Firestore roundtrips.
1526
- Fixed and expanded in-line documentation.
1627

1728
## FetchImage 0.3.0
1829

19-
*Dec 26, 2020*
30+
*December 26, 2020*
2031

2132
- **Breaking Change** `FetchImage` no longer starts the request in the initializer, you must call `fetch()`.
2233
- Add `reset()` method which clears the entire `FetchImage` state including the downloaded image. This is crucial for long lists where you don't want `FetchImage` instances to retain images which are off screen.
@@ -35,6 +46,6 @@
3546

3647
## FetchImage 0.1.0
3748

38-
*Mar 19, 2020*
49+
*March 19, 2020*
3950

4051
- Initial release. See an [introductory post](https://kean.github.io/post/introducing-fetch-image) for more information.

Package.resolved

Lines changed: 27 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Package.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ let package = Package(
1414
.library(name: "FetchImage", targets: ["FetchImage"])
1515
],
1616
dependencies: [
17-
.package(url: "https://github.com/kean/Nuke.git", from: "9.2.0"),
18-
.package(name: "Firebase", url: "https://github.com/firebase/firebase-ios-sdk.git", from: "7.3.0")
17+
.package(url: "https://github.com/kean/Nuke.git", from: "9.5.0"),
18+
.package(name: "Firebase", url: "https://github.com/firebase/firebase-ios-sdk.git", from: "7.10.0")
1919
],
2020
targets: [
2121
.target(name: "FetchImage",

Source/FetchImage.swift

Lines changed: 66 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
//
12
// The MIT License (MIT)
23
//
34
// Copyright (c) 2020 Alexander Grebenyuk (github.com/kean).
5+
//
46

57
import SwiftUI
68
import Nuke
@@ -83,15 +85,17 @@ public final class FetchImage: ObservableObject, Identifiable {
8385
}
8486

8587
func getRegularURL() {
86-
regularStorageRef.downloadURL { (discoveredURL, error) in
87-
if let given = discoveredURL {
88-
let newRequest = ImageRequest(url: given)
89-
self.request = newRequest
90-
self.priority = newRequest.priority
91-
92-
finishOrLoad(newRequest, discoveredURL: given)
93-
} else {
94-
finished?(discoveredURL)
88+
DispatchQueue.global(qos: .userInteractive).async {
89+
regularStorageRef.downloadURL { (discoveredURL, error) in
90+
if let given = discoveredURL {
91+
let newRequest = ImageRequest(url: given)
92+
self.request = newRequest
93+
self.priority = newRequest.priority
94+
95+
finishOrLoad(newRequest, discoveredURL: given)
96+
} else {
97+
finished?(discoveredURL)
98+
}
9599
}
96100
}
97101
}
@@ -117,12 +121,6 @@ public final class FetchImage: ObservableObject, Identifiable {
117121
/// Starts loading the image if not already loaded and the download is not already
118122
/// in progress.
119123
///
120-
/// - note: Low Data Mode. If the `lowDataRequest` is provided and the regular
121-
/// request fails because of the constrained network access, the fetcher tries to
122-
/// download the low-quality image. The fetcher always tries to get the high quality
123-
/// image. If the first attempt fails, the next time you call `fetch`, it is going
124-
/// to attempt to fetch the regular quality image again.
125-
///
126124
public func load(_ request: ImageRequest) {
127125
_reset()
128126

@@ -136,31 +134,38 @@ public final class FetchImage: ObservableObject, Identifiable {
136134

137135
// Try to display the regular image if it is available in memory cache
138136
if let container = pipeline.cachedImage(for: request) {
139-
image = container.image
137+
Thread.executeOnMain {
138+
self.image = container.image
139+
}
140140
return // Nothing to do
141141
}
142142

143-
isLoading = true
143+
Thread.executeOnMain {
144+
self.isLoading = true
145+
}
144146
_load(request: request)
145147
}
146148

147149
private func _load(request: ImageRequest) {
148-
progress = Progress(completed: 0, total: 0)
149-
currentlyLoadingImageQuality = quality
150+
Thread.executeOnMain {
151+
self.progress = Progress(completed: 0, total: 0)
152+
}
150153

151154
task = pipeline.loadImage(
152155
with: request,
153-
progress: { [weak self] response, completed, total in
154-
guard let self = self else { return }
155-
156-
self.progress = Progress(completed: completed, total: total)
156+
progress: { response, completed, total in
157+
Thread.executeOnMain {
158+
self.progress = Progress(completed: completed, total: total)
159+
}
157160

158161
if let image = response?.image {
159-
self.image = image // Display progressively decoded image
162+
Thread.executeOnMain {
163+
self.image = image // Display progressively decoded image
164+
}
160165
}
161166
},
162-
completion: { [weak self] in
163-
self?.didFinishRequest(result: $0)
167+
completion: { result in
168+
self.didFinishRequest(result: result)
164169
}
165170
)
166171

@@ -170,15 +175,22 @@ public final class FetchImage: ObservableObject, Identifiable {
170175
}
171176

172177
private func didFinishRequest(result: Result<ImageResponse, ImagePipeline.Error>) {
173-
task = nil
174-
isLoading = false
178+
defer {
179+
task = nil
180+
Thread.executeOnMain {
181+
self.isLoading = false
182+
}
183+
}
175184

176185
switch result {
177186
case let .success(response):
178-
self.image = response.image
187+
Thread.executeOnMain {
188+
self.image = response.image
189+
}
179190
case let .failure(error):
180-
self.error = error
181-
isLoading = false
191+
Thread.executeOnMain {
192+
self.error = error
193+
}
182194
}
183195
}
184196

@@ -190,7 +202,9 @@ public final class FetchImage: ObservableObject, Identifiable {
190202
public func cancel() {
191203
task?.cancel() // Guarantees that no more callbacks are will be delivered
192204
task = nil
193-
isLoading = false
205+
Thread.executeOnMain {
206+
self.isLoading = false
207+
}
194208
}
195209

196210
/// Resets the `FetchImage` instance by cancelling the request and removing all of
@@ -202,11 +216,12 @@ public final class FetchImage: ObservableObject, Identifiable {
202216
}
203217

204218
private func _reset() {
205-
isLoading = false
206-
image = nil
207-
error = nil
208-
progress = Progress(completed: 0, total: 0)
209-
loadedImageQuality = nil
219+
Thread.executeOnMain {
220+
self.isLoading = false
221+
self.image = nil
222+
self.error = nil
223+
self.progress = Progress(completed: 0, total: 0)
224+
}
210225
request = nil
211226
}
212227

@@ -223,3 +238,17 @@ public extension FetchImage {
223238
}
224239

225240
}
241+
242+
fileprivate extension Thread {
243+
244+
class func executeOnMain(_ mainBlock: @escaping () -> Void) {
245+
if Thread.isMainThread == true {
246+
mainBlock()
247+
} else {
248+
DispatchQueue.main.async {
249+
mainBlock()
250+
}
251+
}
252+
}
253+
254+
}

0 commit comments

Comments
 (0)