diff --git a/FirebaseStorageUI/Sources/FIRStorageDownloadTask+SDWebImage.m b/FirebaseStorageUI/Sources/FIRStorageDownloadTask+SDWebImage.m index e7e34a42a3f..db1e69445d4 100644 --- a/FirebaseStorageUI/Sources/FIRStorageDownloadTask+SDWebImage.m +++ b/FirebaseStorageUI/Sources/FIRStorageDownloadTask+SDWebImage.m @@ -16,6 +16,17 @@ #import "FirebaseStorageUI/Sources/Public/FirebaseStorageUI/FIRStorageDownloadTask+SDWebImage.h" +// For SPM builds the header is empty (no @import, no @interface) to keep the +// Clang module scanner happy. Provide the full import and category declaration +// here where @import is safe (compilation phase, not scan phase). +#if !__has_include() && !__has_include() +@import FirebaseStorage; +NS_ASSUME_NONNULL_BEGIN +@interface FIRStorageDownloadTask (SDWebImage) +@end +NS_ASSUME_NONNULL_END +#endif + @implementation FIRStorageDownloadTask (SDWebImage) @end diff --git a/FirebaseStorageUI/Sources/FUIStorageImageLoader.m b/FirebaseStorageUI/Sources/FUIStorageImageLoader.m index ed94fedec51..9379bb619c8 100644 --- a/FirebaseStorageUI/Sources/FUIStorageImageLoader.m +++ b/FirebaseStorageUI/Sources/FUIStorageImageLoader.m @@ -126,33 +126,31 @@ - (BOOL)canRequestImageForURL:(NSURL *)url { }]; // Observe the progress changes [download observeStatus:FIRStorageTaskStatusProgress handler:^(FIRStorageTaskSnapshot * _Nonnull snapshot) { - // Check progressive decoding if need + // Progressive decoding requires access to partial data via the internal GTMSessionFetcher, + // which was removed in Firebase Storage 9.0.0. Guard to prevent crash; progressive rendering + // is silently skipped on Firebase 9+. if (options & SDWebImageProgressiveLoad) { FIRStorageDownloadTask *task = (FIRStorageDownloadTask *)snapshot.task; - // Currently, FIRStorageDownloadTask does not have the API to grab partial data - // But since FirebaseUI and Firebase are seamless component, we access the internal fetcher here - GTMSessionFetcher *fetcher = task.fetcher; - // Get the partial image data - NSData *partialData = [fetcher.downloadedData copy]; - // Get response - int64_t expectedSize = fetcher.response.expectedContentLength; - expectedSize = expectedSize > 0 ? expectedSize : 0; - int64_t receivedSize = fetcher.downloadedLength; - if (expectedSize != 0) { - // Get the finish status - BOOL finished = receivedSize >= expectedSize; - // This progress block may be called on main queue or global queue (depends configuration), always dispatched on coder queue - if (coderQueue.operationCount == 0) { - [coderQueue addOperationWithBlock:^{ - UIImage *image = SDImageLoaderDecodeProgressiveImageData(partialData, url, finished, task, options, context); - if (image) { - dispatch_main_async_safe(^{ - if (completedBlock) { - completedBlock(image, partialData, nil, NO); - } - }); - } - }]; + if ([task respondsToSelector:@selector(fetcher)]) { + GTMSessionFetcher *fetcher = [task performSelector:@selector(fetcher)]; + NSData *partialData = [fetcher.downloadedData copy]; + int64_t expectedSize = fetcher.response.expectedContentLength; + expectedSize = expectedSize > 0 ? expectedSize : 0; + int64_t receivedSize = fetcher.downloadedLength; + if (expectedSize != 0) { + BOOL finished = receivedSize >= expectedSize; + if (coderQueue.operationCount == 0) { + [coderQueue addOperationWithBlock:^{ + UIImage *image = SDImageLoaderDecodeProgressiveImageData(partialData, url, finished, task, options, context); + if (image) { + dispatch_main_async_safe(^{ + if (completedBlock) { + completedBlock(image, partialData, nil, NO); + } + }); + } + }]; + } } } } @@ -164,7 +162,7 @@ - (BOOL)canRequestImageForURL:(NSURL *)url { } }]; - return download; + return (id)download; } - (BOOL)shouldBlockFailedURLWithURL:(NSURL *)url error:(NSError *)error { diff --git a/FirebaseStorageUI/Sources/NSURL+FirebaseStorage.m b/FirebaseStorageUI/Sources/NSURL+FirebaseStorage.m index caeb05371f7..7805eab3870 100644 --- a/FirebaseStorageUI/Sources/NSURL+FirebaseStorage.m +++ b/FirebaseStorageUI/Sources/NSURL+FirebaseStorage.m @@ -17,6 +17,14 @@ #import "FirebaseStorageUI/Sources/Public/FirebaseStorageUI/NSURL+FirebaseStorage.h" #import +#if __has_include() + #import +#elif __has_include() + #import +#else + @import FirebaseStorage; +#endif + @implementation NSURL (FirebaseStorage) - (FIRStorageReference *)sd_storageReference { diff --git a/FirebaseStorageUI/Sources/Public/FirebaseStorageUI/FIRStorageDownloadTask+SDWebImage.h b/FirebaseStorageUI/Sources/Public/FirebaseStorageUI/FIRStorageDownloadTask+SDWebImage.h index 5bfc6723caf..ac6ae4446d3 100644 --- a/FirebaseStorageUI/Sources/Public/FirebaseStorageUI/FIRStorageDownloadTask+SDWebImage.h +++ b/FirebaseStorageUI/Sources/Public/FirebaseStorageUI/FIRStorageDownloadTask+SDWebImage.h @@ -14,22 +14,24 @@ // limitations under the License. // +#import + +// The category declaration requires FIRStorageDownloadTask to be fully defined, +// which is only possible when the CocoaPods-style headers are present. +// For SPM builds the declaration (and @import FirebaseStorage) live in the .m file +// so the Clang module scanner never sees @import here. #if __has_include() - // Firebase 8.x + // Firebase 8.x (CocoaPods) #import + NS_ASSUME_NONNULL_BEGIN + @interface FIRStorageDownloadTask (SDWebImage) + @end + NS_ASSUME_NONNULL_END #elif __has_include() - // Firebase 9.0+ + // Firebase 9.0+ (CocoaPods) #import -#else - @import FirebaseStorage; + NS_ASSUME_NONNULL_BEGIN + @interface FIRStorageDownloadTask (SDWebImage) + @end + NS_ASSUME_NONNULL_END #endif -#import - -NS_ASSUME_NONNULL_BEGIN - -// `FIRStorageDownloadTask` conforms to `SDWebImageOperation` protocol -@interface FIRStorageDownloadTask (SDWebImage) - -@end - -NS_ASSUME_NONNULL_END diff --git a/FirebaseStorageUI/Sources/Public/FirebaseStorageUI/FUIStorageDefine.h b/FirebaseStorageUI/Sources/Public/FirebaseStorageUI/FUIStorageDefine.h index b45c8905f62..0032705a26c 100644 --- a/FirebaseStorageUI/Sources/Public/FirebaseStorageUI/FUIStorageDefine.h +++ b/FirebaseStorageUI/Sources/Public/FirebaseStorageUI/FUIStorageDefine.h @@ -14,15 +14,6 @@ // limitations under the License. // -#if __has_include() - // Firebase 8.x - #import -#elif __has_include() - // Firebase 9.0+ - #import -#else - @import FirebaseStorage; -#endif #import /** diff --git a/FirebaseStorageUI/Sources/Public/FirebaseStorageUI/NSURL+FirebaseStorage.h b/FirebaseStorageUI/Sources/Public/FirebaseStorageUI/NSURL+FirebaseStorage.h index 1c36fc2dc49..0e0f8128631 100644 --- a/FirebaseStorageUI/Sources/Public/FirebaseStorageUI/NSURL+FirebaseStorage.h +++ b/FirebaseStorageUI/Sources/Public/FirebaseStorageUI/NSURL+FirebaseStorage.h @@ -16,13 +16,14 @@ #import #if __has_include() - // Firebase 8.x + // Firebase 8.x (CocoaPods) #import #elif __has_include() - // Firebase 9.0+ + // Firebase 9.0+ (CocoaPods) #import #else - @import FirebaseStorage; + // Swift Package Manager: forward declaration only. + @class FIRStorageReference; #endif NS_ASSUME_NONNULL_BEGIN diff --git a/FirebaseStorageUI/Sources/Public/FirebaseStorageUI/UIImageView+FirebaseStorage.h b/FirebaseStorageUI/Sources/Public/FirebaseStorageUI/UIImageView+FirebaseStorage.h index cca051ad694..82e709e575b 100644 --- a/FirebaseStorageUI/Sources/Public/FirebaseStorageUI/UIImageView+FirebaseStorage.h +++ b/FirebaseStorageUI/Sources/Public/FirebaseStorageUI/UIImageView+FirebaseStorage.h @@ -17,21 +17,18 @@ #import #if __has_include() - // Firebase 8.x + // Firebase 8.x (CocoaPods) #import #elif (__has_include()) - // Firebase 9.0+ + // Firebase 9.0+ (CocoaPods) #import #else - // If you're using FirebaseStorageUI via Swift Package Manager - // from a Swift or mixed Swift/ObjC build target, you will need - // to add - // -Xcc -fmodule-map-file=$(GENERATED_MODULEMAP_DIR)/FirebaseStorage.modulemap - // to your target's Other Swift Flags build setting. - // See - // https://github.com/firebase/FirebaseUI-iOS/issues/1028#issuecomment-1262689219 - // for more details. - @import FirebaseStorage; + // Swift Package Manager: forward declarations only to avoid Clang module-scanner + // failures. Your app target must `@import FirebaseStorage` (or `import FirebaseStorage` + // in Swift) separately. + @class FIRStorage; + @class FIRStorageReference; + @class FIRStorageDownloadTask; #endif #import diff --git a/FirebaseStorageUI/Sources/UIImageView+FirebaseStorage.m b/FirebaseStorageUI/Sources/UIImageView+FirebaseStorage.m index 39fb2571fce..882f0dd65b6 100644 --- a/FirebaseStorageUI/Sources/UIImageView+FirebaseStorage.m +++ b/FirebaseStorageUI/Sources/UIImageView+FirebaseStorage.m @@ -17,6 +17,14 @@ #import "FirebaseStorageUI/Sources/Public/FirebaseStorageUI/UIImageView+FirebaseStorage.h" #import "FirebaseStorageUI/Sources/Public/FirebaseStorageUI/FUIStorageImageLoader.h" +#if __has_include() + #import +#elif __has_include() + #import +#else + @import FirebaseStorage; +#endif + @implementation UIImageView (FirebaseStorage) - (void)sd_setImageWithStorageReference:(FIRStorageReference *)storageRef {