Skip to content

Commit a53db1a

Browse files
authored
[v11] Streamline internal FirebaseStorageTask implementations (#13220)
1 parent 0ab171c commit a53db1a

26 files changed

+316
-502
lines changed

FirebaseStorage/Sources/Internal/StorageDeleteTask.swift

+13-54
Original file line numberDiff line numberDiff line change
@@ -20,59 +20,18 @@ import Foundation
2020
import GTMSessionFetcherCore
2121
#endif
2222

23-
/**
24-
* Task which provides the ability to delete an object in Firebase Storage.
25-
*/
26-
class StorageDeleteTask: StorageTask, StorageTaskManagement {
27-
private var fetcher: GTMSessionFetcher?
28-
private var fetcherCompletion: ((Data?, NSError?) -> Void)?
29-
private var taskCompletion: ((_ error: Error?) -> Void)?
30-
31-
init(reference: StorageReference,
32-
fetcherService: GTMSessionFetcherService,
33-
queue: DispatchQueue,
34-
completion: ((_: Error?) -> Void)?) {
35-
super.init(reference: reference, service: fetcherService, queue: queue)
36-
taskCompletion = completion
37-
}
38-
39-
deinit {
40-
self.fetcher?.stopFetching()
41-
}
42-
43-
/**
44-
* Prepares a task and begins execution.
45-
*/
46-
func enqueue() {
47-
let completion = taskCompletion
48-
taskCompletion = { (error: Error?) in
49-
completion?(error)
50-
// Reference self in completion handler in order to retain self until completion is called.
51-
self.taskCompletion = nil
52-
}
53-
dispatchQueue.async { [weak self] in
54-
guard let self = self else { return }
55-
self.state = .queueing
56-
var request = self.baseRequest
57-
request.httpMethod = "DELETE"
58-
request.timeoutInterval = self.reference.storage.maxOperationRetryTime
59-
60-
let fetcher = self.fetcherService.fetcher(with: request)
61-
fetcher.comment = "DeleteTask"
62-
self.fetcher = fetcher
63-
64-
self.fetcherCompletion = { [weak self] (data: Data?, error: NSError?) in
65-
guard let self = self else { return }
66-
if let error, self.error == nil {
67-
self.error = StorageErrorCode.error(withServerError: error, ref: self.reference)
68-
}
69-
self.taskCompletion?(self.error)
70-
self.fetcherCompletion = nil
71-
}
72-
73-
self.fetcher?.beginFetch { [weak self] data, error in
74-
self?.fetcherCompletion?(data, error as? NSError)
75-
}
76-
}
23+
/// Task which provides the ability to delete an object in Firebase Storage.
24+
@available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *)
25+
enum StorageDeleteTask {
26+
static func deleteTask(reference: StorageReference,
27+
fetcherService: GTMSessionFetcherService,
28+
queue: DispatchQueue,
29+
completion: ((_: Data?, _: Error?) -> Void)?) {
30+
StorageInternalTask(reference: reference,
31+
fetcherService: fetcherService,
32+
queue: queue,
33+
httpMethod: "DELETE",
34+
fetcherComment: "DeleteTask",
35+
completion: completion)
7736
}
7837
}

FirebaseStorage/Sources/Internal/StorageGetDownloadURLTask.swift

+30-67
Original file line numberDiff line numberDiff line change
@@ -20,80 +20,43 @@ import Foundation
2020
import GTMSessionFetcherCore
2121
#endif
2222

23-
/**
24-
* Task which provides the ability to get a download URL for an object in Firebase Storage.
25-
*/
26-
class StorageGetDownloadURLTask: StorageTask, StorageTaskManagement {
27-
private var fetcher: GTMSessionFetcher?
28-
private var fetcherCompletion: ((Data?, NSError?) -> Void)?
29-
private var taskCompletion: ((_ downloadURL: URL?, _: Error?) -> Void)?
30-
31-
init(reference: StorageReference,
32-
fetcherService: GTMSessionFetcherService,
33-
queue: DispatchQueue,
34-
completion: ((_: URL?, _: Error?) -> Void)?) {
35-
super.init(reference: reference, service: fetcherService, queue: queue)
36-
taskCompletion = completion
37-
}
38-
39-
deinit {
40-
self.fetcher?.stopFetching()
41-
}
42-
43-
/**
44-
* Prepares a task and begins execution.
45-
*/
46-
func enqueue() {
47-
if let completion = taskCompletion {
48-
taskCompletion = { (url: URL?, error: Error?) in
49-
completion(url, error)
50-
// Reference self in completion handler in order to retain self until completion is called.
51-
self.taskCompletion = nil
52-
}
53-
}
54-
dispatchQueue.async { [weak self] in
55-
guard let self = self else { return }
56-
var request = self.baseRequest
57-
request.httpMethod = "GET"
58-
request.timeoutInterval = self.reference.storage.maxOperationRetryTime
59-
60-
let fetcher = self.fetcherService.fetcher(with: request)
61-
fetcher.comment = "GetDownloadURLTask"
62-
self.fetcher = fetcher
63-
64-
self.fetcherCompletion = { [weak self] (data: Data?, error: NSError?) in
65-
guard let self = self else { return }
66-
var downloadURL: URL?
67-
if let error {
68-
if self.error == nil {
69-
self.error = StorageErrorCode.error(withServerError: error, ref: self.reference)
23+
/// Task which provides the ability to get a download URL for an object in Firebase Storage.
24+
@available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *)
25+
enum StorageGetDownloadURLTask {
26+
static func getDownloadURLTask(reference: StorageReference,
27+
fetcherService: GTMSessionFetcherService,
28+
queue: DispatchQueue,
29+
completion: ((_: URL?, _: Error?) -> Void)?) {
30+
StorageInternalTask(reference: reference,
31+
fetcherService: fetcherService,
32+
queue: queue,
33+
httpMethod: "GET",
34+
fetcherComment: "GetDownloadURLTask") { (data: Data?, error: Error?) in
35+
if let error {
36+
completion?(nil, error)
37+
} else {
38+
if let data,
39+
let responseDictionary = try? JSONSerialization
40+
.jsonObject(with: data) as? [String: Any] {
41+
guard let downloadURL = downloadURLFromMetadataDictionary(responseDictionary,
42+
reference) else {
43+
let error = StorageError.unknown(
44+
message: "Failed to retrieve a download URL.",
45+
serverError: [:]
46+
) as NSError
47+
completion?(nil, error)
48+
return
7049
}
50+
completion?(downloadURL, nil)
7151
} else {
72-
if let data,
73-
let responseDictionary = try? JSONSerialization
74-
.jsonObject(with: data) as? [String: Any] {
75-
downloadURL = self.downloadURLFromMetadataDictionary(responseDictionary)
76-
if downloadURL == nil {
77-
self.error = StorageError.unknown(
78-
message: "Failed to retrieve a download URL.",
79-
serverError: [:]
80-
) as NSError
81-
}
82-
} else {
83-
self.error = StorageErrorCode.error(withInvalidRequest: data)
84-
}
52+
completion?(nil, StorageErrorCode.error(withInvalidRequest: data))
8553
}
86-
self.taskCompletion?(downloadURL, self.error)
87-
self.fetcherCompletion = nil
88-
}
89-
90-
self.fetcher?.beginFetch { [weak self] data, error in
91-
self?.fetcherCompletion?(data, error as? NSError)
9254
}
9355
}
9456
}
9557

96-
func downloadURLFromMetadataDictionary(_ dictionary: [String: Any]) -> URL? {
58+
static func downloadURLFromMetadataDictionary(_ dictionary: [String: Any],
59+
_ reference: StorageReference) -> URL? {
9760
let downloadTokens = dictionary["downloadTokens"]
9861
guard let downloadTokens = downloadTokens as? String,
9962
downloadTokens.count > 0 else {

FirebaseStorage/Sources/Internal/StorageGetMetadataTask.swift

+22-63
Original file line numberDiff line numberDiff line change
@@ -20,71 +20,30 @@ import Foundation
2020
import GTMSessionFetcherCore
2121
#endif
2222

23-
/**
24-
* Task which provides the ability to delete an object in Firebase Storage.
25-
*/
26-
class StorageGetMetadataTask: StorageTask, StorageTaskManagement {
27-
private var fetcher: GTMSessionFetcher?
28-
private var fetcherCompletion: ((Data?, NSError?) -> Void)?
29-
private var taskCompletion: ((_ metadata: StorageMetadata?, _: Error?) -> Void)?
30-
31-
init(reference: StorageReference,
32-
fetcherService: GTMSessionFetcherService,
33-
queue: DispatchQueue,
34-
completion: ((_: StorageMetadata?, _: Error?) -> Void)?) {
35-
super.init(reference: reference, service: fetcherService, queue: queue)
36-
taskCompletion = completion
37-
}
38-
39-
deinit {
40-
self.fetcher?.stopFetching()
41-
}
42-
43-
/**
44-
* Prepares a task and begins execution.
45-
*/
46-
func enqueue() {
47-
if let completion = taskCompletion {
48-
taskCompletion = { (metadata: StorageMetadata?, error: Error?) in
49-
completion(metadata, error)
50-
// Reference self in completion handler in order to retain self until completion is called.
51-
self.taskCompletion = nil
52-
}
53-
}
54-
dispatchQueue.async { [weak self] in
55-
guard let self = self else { return }
56-
self.state = .queueing
57-
var request = self.baseRequest
58-
request.httpMethod = "GET"
59-
request.timeoutInterval = self.reference.storage.maxOperationRetryTime
60-
61-
let fetcher = self.fetcherService.fetcher(with: request)
62-
fetcher.comment = "GetMetadataTask"
63-
self.fetcher = fetcher
64-
65-
self.fetcherCompletion = { [weak self] (data: Data?, error: NSError?) in
66-
guard let self = self else { return }
67-
var metadata: StorageMetadata?
68-
if let error {
69-
if self.error == nil {
70-
self.error = StorageErrorCode.error(withServerError: error, ref: self.reference)
71-
}
23+
/// Task which provides the ability to delete an object in Firebase Storage.
24+
@available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *)
25+
enum StorageGetMetadataTask {
26+
static func getMetadataTask(reference: StorageReference,
27+
fetcherService: GTMSessionFetcherService,
28+
queue: DispatchQueue,
29+
completion: ((_: StorageMetadata?, _: Error?) -> Void)?) {
30+
StorageInternalTask(reference: reference,
31+
fetcherService: fetcherService,
32+
queue: queue,
33+
httpMethod: "GET",
34+
fetcherComment: "GetMetadataTask") { (data: Data?, error: Error?) in
35+
if let error {
36+
completion?(nil, error)
37+
} else {
38+
if let data,
39+
let responseDictionary = try? JSONSerialization
40+
.jsonObject(with: data) as? [String: AnyHashable] {
41+
let metadata = StorageMetadata(dictionary: responseDictionary)
42+
metadata.fileType = .file
43+
completion?(metadata, nil)
7244
} else {
73-
if let data,
74-
let responseDictionary = try? JSONSerialization
75-
.jsonObject(with: data) as? [String: AnyHashable] {
76-
metadata = StorageMetadata(dictionary: responseDictionary)
77-
metadata?.fileType = .file
78-
} else {
79-
self.error = StorageErrorCode.error(withInvalidRequest: data)
80-
}
45+
completion?(nil, StorageErrorCode.error(withInvalidRequest: data))
8146
}
82-
self.taskCompletion?(metadata, self.error)
83-
self.fetcherCompletion = nil
84-
}
85-
86-
self.fetcher?.beginFetch { [weak self] data, error in
87-
self?.fetcherCompletion?(data, error as? NSError)
8847
}
8948
}
9049
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Copyright 2024 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
import Foundation
16+
17+
#if COCOAPODS
18+
import GTMSessionFetcher
19+
#else
20+
import GTMSessionFetcherCore
21+
#endif
22+
23+
/// Implement StorageTasks that are not directly exposed via the public API.
24+
@available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *)
25+
class StorageInternalTask: StorageTask {
26+
private var fetcher: GTMSessionFetcher?
27+
28+
@discardableResult
29+
init(reference: StorageReference,
30+
fetcherService: GTMSessionFetcherService,
31+
queue: DispatchQueue,
32+
request: URLRequest? = nil,
33+
httpMethod: String,
34+
fetcherComment: String,
35+
completion: ((_: Data?, _: Error?) -> Void)?) {
36+
super.init(reference: reference, service: fetcherService, queue: queue)
37+
38+
// Prepare a task and begins execution.
39+
dispatchQueue.async { [self] in
40+
self.state = .queueing
41+
var request = request ?? self.baseRequest
42+
request.httpMethod = httpMethod
43+
request.timeoutInterval = self.reference.storage.maxOperationRetryTime
44+
45+
let fetcher = self.fetcherService.fetcher(with: request)
46+
fetcher.comment = fetcherComment
47+
self.fetcher = fetcher
48+
49+
Task {
50+
do {
51+
let data = try await self.fetcher?.beginFetch()
52+
completion?(data, nil)
53+
} catch {
54+
completion?(nil, StorageErrorCode.error(withServerError: error as NSError,
55+
ref: self.reference))
56+
}
57+
}
58+
}
59+
}
60+
61+
deinit {
62+
self.fetcher?.stopFetching()
63+
}
64+
}

0 commit comments

Comments
 (0)