Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
/// The publisher will emit events on the **main** thread.
///
/// - Parameters:
/// - size: The maximum size in bytes to download. If the download exceeds this size
/// - size: The maximum size in bytes to download. If the download exceeds this size,
/// the task will be cancelled and an error will be returned.
///
/// - Returns: A publisher emitting a `Data` instance. The publisher will emit on the *main* thread.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ NS_SWIFT_NAME(putData(_:metadata:));
* Asynchronously downloads the object at the FIRStorageReference to an NSData object in memory.
* An NSData of the provided max size will be allocated, so ensure that the device has enough free
* memory to complete the download. For downloading large files, writeToFile may be a better option.
* @param size The maximum size in bytes to download. If the download exceeds this size
* @param size The maximum size in bytes to download. If the download exceeds this size,
* the task will be cancelled and an error will be returned.
* @param completion A completion block that either returns the object data on success,
* or an error on failure.
Expand All @@ -194,7 +194,7 @@ NS_SWIFT_NAME(putData(_:metadata:));
/**
* Asynchronously retrieves a long lived download URL with a revokable token.
* This can be used to share the file with others, but can be revoked by a developer
* in the Firebase Console if desired.
* in the Firebase Console.
* @param completion A completion block that either returns the URL on success,
* or an error on failure.
*/
Expand Down
6 changes: 6 additions & 0 deletions FirebaseStorageSwift/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# 8.5.0-beta
- Added four APIs to augment automatically generated `async/await` APIs. See
details via Xcode completion and at the
[source](https://github.com/firebase/firebase-ios-sdk/blob/96d60a6d472b6fed1651d5e7a0e7495230c220ec/FirebaseStorageSwift/Sources/AsyncAwait.swift).
Feedback appreciated about Firebase and `async/await`. (#8289)

# v0.1
- Initial public beta release. Extends the Storage Reference API with the Swift
Result type for all APIs that return an optional value and optional Error.
Expand Down
92 changes: 92 additions & 0 deletions FirebaseStorageSwift/Sources/AsyncAwait.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import FirebaseStorage

#if swift(>=5.5)
@available(iOS 15, *)
public extension StorageReference {
/// Asynchronously downloads the object at the StorageReference to a Data object in memory.
/// A Data object of the provided max size will be allocated, so ensure that the device has
/// enough free memory to complete the download. For downloading large files, the `write`
/// API may be a better option.
///
/// - Parameters:
/// - size: The maximum size in bytes to download. If the download exceeds this size,
/// the task will be cancelled and an error will be thrown.
/// - Returns: Data object.
func data(maxSize: Int64) async throws -> Data {
typealias DataContinuation = CheckedContinuation<Data, Error>
return try await withCheckedThrowingContinuation { (continuation: DataContinuation) in
// TODO: Use task to handle progress and cancellation.
_ = self.getData(maxSize: maxSize) { result in
continuation.resume(with: result)
}
}
}

/// Asynchronously uploads data to the currently specified StorageReference.
/// This is not recommended for large files, and one should instead upload a file from disk
/// from the Firebase Console.
///
/// - Parameters:
/// - uploadData: The Data to upload.
/// - metadata: Optional StorageMetadata containing additional information (MIME type, etc.)
/// about the object being uploaded.
/// - Returns: StorageMetadata with additional information about the object being uploaded.
func putDataAsync(_ uploadData: Data,
metadata: StorageMetadata? = nil) async throws -> StorageMetadata {
typealias MetadataContinuation = CheckedContinuation<StorageMetadata, Error>
return try await withCheckedThrowingContinuation { (continuation: MetadataContinuation) in
// TODO: Use task to handle progress and cancellation.
_ = self.putData(uploadData, metadata: metadata) { result in
continuation.resume(with: result)
}
}
}

/// Asynchronously uploads a file to the currently specified StorageReference.
///
/// - Parameters:
/// - url: A URL representing the system file path of the object to be uploaded.
/// - metadata: Optional StorageMetadata containing additional information (MIME type, etc.)
/// about the object being uploaded.
/// - Returns: StorageMetadata with additional information about the object being uploaded.
func putFileAsync(from url: URL,
metadata: StorageMetadata? = nil) async throws -> StorageMetadata {
typealias MetadataContinuation = CheckedContinuation<StorageMetadata, Error>
return try await withCheckedThrowingContinuation { (continuation: MetadataContinuation) in
// TODO: Use task to handle progress and cancellation.
_ = self.putFile(from: url, metadata: metadata) { result in
continuation.resume(with: result)
}
}
}

/// Asynchronously downloads the object at the current path to a specified system filepath.
///
/// - Parameters:
/// - fileUrl: A URL representing the system file path of the object to be uploaded.
/// - Returns: URL pointing to the file path of the downloaded file.
func writeAsync(toFile fileURL: URL) async throws -> URL {
typealias URLContinuation = CheckedContinuation<URL, Error>
return try await withCheckedThrowingContinuation { (continuation: URLContinuation) in
// TODO: Use task to handle progress and cancellation.
_ = self.write(toFile: fileURL) { result in
continuation.resume(with: result)
}
}
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@

import FirebaseStorage

private enum DataError: Error {
case internalInconsistency // Thrown when both value and error are nil.
}

/// Generates a closure that returns a `Result` type from a closure that returns an optional type
/// and `Error`.
///
Expand All @@ -31,19 +35,15 @@ private func getResultCallback<T>(completion: @escaping (Result<T, Error>) -> Vo
} else if let error = error {
completion(.failure(error))
} else {
completion(.failure(NSError(domain: "FirebaseStorageSwift",
code: -1,
userInfo: [NSLocalizedDescriptionKey:
"InternalError - Return type and Error code both nil in " +
"Storage Result generator"])))
completion(.failure(DataError.internalInconsistency))
}
}
}

public extension StorageReference {
/// Asynchronously retrieves a long lived download URL with a revokable token.
/// This can be used to share the file with others, but can be revoked by a developer
/// in the Firebase Console if desired.
/// in the Firebase Console.
///
/// - Parameters:
/// - completion: A completion block returning a `Result` enum with either a URL or an `Error`.
Expand All @@ -53,7 +53,7 @@ public extension StorageReference {

/// Asynchronously downloads the object at the `StorageReference` to a `Data` object.
/// A `Data` of the provided max size will be allocated, so ensure that the device has enough
/// memory to complete. For downloading large files, writeToFile may be a better option.
/// memory to complete. For downloading large files, the `write` API may be a better option.

/// - Parameters:
/// - maxSize: The maximum size in bytes to download.
Expand Down
Loading