@@ -9,44 +9,14 @@ import FirebaseStorage
99/// Fetch a remote image and progressively load using cached resources first, if
1010/// available, then displaying a placeholder until fully loaded.
1111///
12- /// - warning: This is an API preview. It is not battle-tested yet and might
13- /// signficantly change in the future.
14- ///
1512public final class FetchImage : ObservableObject , Identifiable {
1613
1714 // MARK: - Paramaters
1815
1916 /// The original request.
20- public private( set) var request : ImageRequest ? {
21- didSet {
22- assert ( Thread . isMainThread, " Only modify the request from the main thread. " )
23- if currentlyLoadingImageQuality == . regular {
24- cancel ( )
25- }
26- guard let newRequest = request else {
27- if loadedImageQuality == . regular {
28- image = nil
29- }
30- return
31- }
32- priority = newRequest. priority
33- }
34- }
35-
36- /// The request to be performed if the original request fails with
37- /// `networkUnavailableReason` `.constrained` (low data mode).
38- public private( set) var lowDataRequest : ImageRequest ? {
39- didSet {
40- assert ( Thread . isMainThread, " Only modify the request from the main thread. " )
41- if currentlyLoadingImageQuality == . low {
42- cancel ( )
43- }
44- if lowDataRequest == nil && loadedImageQuality == . low {
45- image = nil
46- }
47- }
48- }
49-
17+ ///
18+ public private( set) var request : ImageRequest ?
19+
5020 /// Returns the fetched image.
5121 ///
5222 /// - note: In case pipeline has `isProgressiveDecodingEnabled` option enabled
@@ -79,42 +49,17 @@ public final class FetchImage: ObservableObject, Identifiable {
7949
8050 public var pipeline : ImagePipeline = . shared
8151 private var task : ImageTask ?
82- private var loadedImageQuality : ImageQuality ?
83- private var currentlyLoadingImageQuality : ImageQuality ? = nil
84-
85- private enum ImageQuality {
86- case regular
87- case low
88- }
89-
9052
9153 // MARK: - Lifecycle
9254
9355 deinit {
9456 cancel ( )
9557 }
96-
97- public init ( ) {
98-
99- }
100-
101- /// Loads an image with a regular URL and an optional low-data URL.
102- ///
103- /// If supplying an optional low-data URL, disables constrained network access on
104- /// the full size request. If the download fails on the initial full size URL, falls
105- /// back to the low-data URL.
106- ///
107- /// - parameter url: The remote image URL
108- /// - parameter lowDataUrl: The low data remote image URL
109- ///
110- public func load( _ url: URL , lowDataUrl: URL ? = nil ) {
111- var request = URLRequest ( url: url)
112- if let constrainedURL = lowDataUrl {
113- request. allowsConstrainedNetworkAccess = false
114- load ( ImageRequest ( urlRequest: request) , lowDataRequest: ImageRequest ( url: constrainedURL) )
115- } else {
116- load ( ImageRequest ( url: url) )
117- }
58+
59+ public init ( ) { }
60+
61+ public func load( _ url: URL ) {
62+ self . load ( ImageRequest ( url: url) )
11863 }
11964
12065 /// Initializes the fetch request with a Firebase Storage Reference to an image in
@@ -123,32 +68,28 @@ public final class FetchImage: ObservableObject, Identifiable {
12368 ///
12469 /// - parameter regularStorageRef: A `StorageReference` which points to a
12570 /// Firebase Storage file in any of Nuke's supported image formats.
126- /// - parameter lowDataStorageRef: A `StorageReference` which points to a smaller
127- /// Firebase Storage file in any of Nuke's supported image formats, which is also
128- /// appropriate for low-data scenarios.
12971 /// - parameter uniqueURL: A caller to request any potentially cached image URLs.
13072 /// Implementing your own URL caching prevents potentially unnecessary roundtrips to
13173 /// your Firebase Storage bucket.
13274 /// - parameter finished: Called when URL loading has completed and fetching can
13375 /// begin. If the caller is `nil`, a fetch operation is queued immediately.
13476 ///
135- public func load( regularStorageRef: StorageReference , lowDataStorageRef: StorageReference ? = nil ,
136- uniqueURL: ( ( ) -> URL ? ) ? = nil , finished: ( ( URL ? ) -> Void ) ? = nil ) {
137- func finishOrLoad( _ request: ImageRequest , lowDataRequest: ImageRequest ? = nil , discoveredURL: URL ? = nil ) {
77+ public func load( regularStorageRef: StorageReference , uniqueURL: ( ( ) -> URL ? ) ? = nil , finished: ( ( URL ? ) -> Void ) ? = nil ) {
78+ func finishOrLoad( _ request: ImageRequest , discoveredURL: URL ? = nil ) {
13879 if let completionBlock = finished {
13980 completionBlock ( discoveredURL)
14081 }
14182 load ( request)
14283 }
14384
144- func getRegularURL( lowDataRequest : ImageRequest ? = nil ) {
85+ func getRegularURL( ) {
14586 regularStorageRef. downloadURL { ( discoveredURL, error) in
14687 if let given = discoveredURL {
14788 let newRequest = ImageRequest ( url: given)
14889 self . request = newRequest
14990 self . priority = newRequest. priority
15091
151- finishOrLoad ( newRequest, lowDataRequest : lowDataRequest , discoveredURL: given)
92+ finishOrLoad ( newRequest, discoveredURL: given)
15293 } else {
15394 finished ? ( discoveredURL)
15495 }
@@ -168,22 +109,9 @@ public final class FetchImage: ObservableObject, Identifiable {
168109 }
169110 }
170111
171- if let lowDataRef = lowDataStorageRef {
172- lowDataRef. downloadURL { ( discoveredURL, error) in
173- if let given = discoveredURL {
174- let constrainedRequest = ImageRequest ( url: given)
175- self . lowDataRequest = constrainedRequest
176- getRegularURL ( lowDataRequest: constrainedRequest)
177- } else {
178- getRegularURL ( )
179- }
180- }
181- } else {
182- getRegularURL ( )
183- }
112+ getRegularURL ( )
184113 }
185114
186-
187115 // MARK: - Fetching
188116
189117 /// Starts loading the image if not already loaded and the download is not already
@@ -195,7 +123,7 @@ public final class FetchImage: ObservableObject, Identifiable {
195123 /// image. If the first attempt fails, the next time you call `fetch`, it is going
196124 /// to attempt to fetch the regular quality image again.
197125 ///
198- public func load( _ request: ImageRequest , lowDataRequest : ImageRequest ? = nil ) {
126+ public func load( _ request: ImageRequest ) {
199127 _reset ( )
200128
201129 // Cancel previous task after starting a new one to make sure that if
@@ -205,24 +133,18 @@ public final class FetchImage: ObservableObject, Identifiable {
205133 defer { previousTask? . cancel ( ) }
206134
207135 self . request = request
208- self . lowDataRequest = lowDataRequest
209136
210137 // Try to display the regular image if it is available in memory cache
211138 if let container = pipeline. cachedImage ( for: request) {
212- ( image, loadedImageQuality ) = ( container. image, . regular )
139+ image = container. image
213140 return // Nothing to do
214141 }
215142
216- // Try to display the low data image and retry loading the regular image
217- if let container = lowDataRequest. flatMap ( pipeline. cachedImage ( for: ) ) {
218- ( image, loadedImageQuality) = ( container. image, . low)
219- }
220-
221143 isLoading = true
222- load ( request: request, quality : . regular )
144+ _load ( request: request)
223145 }
224-
225- private func load ( request: ImageRequest , quality : ImageQuality ) {
146+
147+ private func _load ( request: ImageRequest ) {
226148 progress = Progress ( completed: 0 , total: 0 )
227149 currentlyLoadingImageQuality = quality
228150
@@ -238,36 +160,25 @@ public final class FetchImage: ObservableObject, Identifiable {
238160 }
239161 } ,
240162 completion: { [ weak self] in
241- self ? . didFinishRequest ( result: $0, quality : quality )
163+ self ? . didFinishRequest ( result: $0)
242164 }
243165 )
244166
245167 if priority != request. priority {
246168 task? . priority = priority
247169 }
248170 }
249-
250- private func didFinishRequest( result: Result < ImageResponse , ImagePipeline . Error > , quality : ImageQuality ) {
171+
172+ private func didFinishRequest( result: Result < ImageResponse , ImagePipeline . Error > ) {
251173 task = nil
252- currentlyLoadingImageQuality = nil
174+ isLoading = false
253175
254176 switch result {
255177 case let . success( response) :
256- isLoading = false
257- ( image, loadedImageQuality) = ( response. image, quality)
178+ self . image = response. image
258179 case let . failure( error) :
259- // If the regular request fails because of the low data mode,
260- // use an alternative source.
261- if quality == . regular, error. isConstrainedNetwork, let request = self . lowDataRequest {
262- if loadedImageQuality == . low {
263- isLoading = false // Low-quality image already loaded
264- } else {
265- load ( request: request, quality: . low)
266- }
267- } else {
268- self . error = error
269- isLoading = false
270- }
180+ self . error = error
181+ isLoading = false
271182 }
272183 }
273184
@@ -289,25 +200,14 @@ public final class FetchImage: ObservableObject, Identifiable {
289200 cancel ( )
290201 _reset ( )
291202 }
292-
203+
293204 private func _reset( ) {
294205 isLoading = false
295206 image = nil
296207 error = nil
297208 progress = Progress ( completed: 0 , total: 0 )
298209 loadedImageQuality = nil
299- }
300-
301- }
302-
303- private extension ImagePipeline . Error {
304-
305- var isConstrainedNetwork : Bool {
306- if case let . dataLoadingFailed( error) = self ,
307- ( error as? URLError ) ? . networkUnavailableReason == . constrained {
308- return true
309- }
310- return false
210+ request = nil
311211 }
312212
313213}
0 commit comments