Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactory the FirebaseUI-Storage binding of SDWebImage using the 5.0 modern Custom Image Loader API. #654

Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
5684746
Refactory the FirebaseUI-Storage binding of SDWebImage, using the mod…
dreampiggy Mar 27, 2019
9f0965a
Change the public API of UIImageView+FirebaseStorage, add the `option…
dreampiggy Mar 28, 2019
7423424
Fix code format. Using 2-space indent instead of 4
dreampiggy Mar 28, 2019
916e6da
Update the comment
dreampiggy Mar 28, 2019
2868bc3
Remove the cache key mapping for old fullpath style cache keys
dreampiggy Mar 29, 2019
7527543
Rename the FirebaseLoader, into the FIRStorageLoader, make it more pr…
dreampiggy Mar 29, 2019
e07b7c5
Add some test for SDWebImageFIRStorageLoader
dreampiggy Mar 29, 2019
02fcbc1
Update some usage demo code
dreampiggy Mar 29, 2019
b20f7a0
Fix the error description of invalid URL
dreampiggy Mar 30, 2019
13fe756
Update some small comments to match the behavior
dreampiggy Mar 30, 2019
eea0416
Upgrade to the official release version SDWebImage 5.0, adapt the API…
dreampiggy Apr 3, 2019
f634c13
Fix the rare case that a path contains the percent sign, will cause c…
dreampiggy Apr 3, 2019
68c49c5
Update the comments of Firebase Storage UI usage
dreampiggy Apr 3, 2019
41236e1
Fix the test case after upgrading the API
dreampiggy Apr 3, 2019
f14bfd9
Revert the changes in Podfile for test case and retry
dreampiggy Apr 28, 2019
9243352
Rename the SDWebImage prefixed class, into the FUI prefix, make it ma…
dreampiggy Apr 28, 2019
40f25cb
Update all Copyright year and comments
dreampiggy Apr 28, 2019
4988ab1
Try to remove the pod install effected project changes. Run pod deint…
dreampiggy Apr 28, 2019
124ff1f
Try again with Podfile modification fo test scheme
dreampiggy Apr 28, 2019
094f0ba
Update the code comment about the callback queue information
dreampiggy Apr 28, 2019
d436ab6
Removed the gs scheme constant, because most people don't need this. …
dreampiggy Apr 28, 2019
68842f1
Merge branch 'master' of https://github.com/firebase/FirebaseUI-iOS i…
dreampiggy May 8, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion FirebaseUI.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Pod::Spec.new do |s|
storage.public_header_files = 'Storage/FirebaseStorageUI/*.h'
storage.source_files = 'Storage/FirebaseStorageUI/*.{h,m}'
storage.dependency 'Firebase/Storage', '~> 5.0'
storage.dependency 'SDWebImage', '~> 4.0'
storage.dependency 'SDWebImage', '~> 5.0'
storage.xcconfig = { 'HEADER_SEARCH_PATHS' => '$(PODS_ROOT)/FirebaseUI/FirebaseStorageUI' }
end

Expand Down
32 changes: 32 additions & 0 deletions Storage/FirebaseStorageUI.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@
objects = {

/* Begin PBXBuildFile section */
32450161224B963B00AF2E90 /* FUIStorageImageLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3245015F224B963B00AF2E90 /* FUIStorageImageLoader.h */; settings = {ATTRIBUTES = (Public, ); }; };
32450162224B963B00AF2E90 /* FUIStorageImageLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 32450160224B963B00AF2E90 /* FUIStorageImageLoader.m */; };
32450165224B96B400AF2E90 /* NSURL+FirebaseStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = 32450163224B96B400AF2E90 /* NSURL+FirebaseStorage.h */; settings = {ATTRIBUTES = (Public, ); }; };
32450166224B96B400AF2E90 /* NSURL+FirebaseStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 32450164224B96B400AF2E90 /* NSURL+FirebaseStorage.m */; };
3245016D224B987400AF2E90 /* FUIStorageDefine.h in Headers */ = {isa = PBXBuildFile; fileRef = 3245016B224B987400AF2E90 /* FUIStorageDefine.h */; settings = {ATTRIBUTES = (Public, ); }; };
3245016E224B987400AF2E90 /* FUIStorageDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = 3245016C224B987400AF2E90 /* FUIStorageDefine.m */; };
32A5DB2722755E480029B3D5 /* FIRStorageDownloadTask+SDWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 32A5DB2522755E480029B3D5 /* FIRStorageDownloadTask+SDWebImage.h */; settings = {ATTRIBUTES = (Public, ); }; };
32A5DB2822755E480029B3D5 /* FIRStorageDownloadTask+SDWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 32A5DB2622755E480029B3D5 /* FIRStorageDownloadTask+SDWebImage.m */; };
8D69E60621DE968300CFA49B /* FirebaseStorageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D69E5FC21DE968300CFA49B /* FirebaseStorageUI.framework */; };
8D69E60D21DE968300CFA49B /* FirebaseStorageUI.h in Headers */ = {isa = PBXBuildFile; fileRef = 8D69E5FF21DE968300CFA49B /* FirebaseStorageUI.h */; settings = {ATTRIBUTES = (Public, ); }; };
8D69E61821DE96CF00CFA49B /* UIImageView+FirebaseStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D69E61621DE96CF00CFA49B /* UIImageView+FirebaseStorage.m */; };
Expand All @@ -25,6 +33,14 @@
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
3245015F224B963B00AF2E90 /* FUIStorageImageLoader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FUIStorageImageLoader.h; sourceTree = "<group>"; };
32450160224B963B00AF2E90 /* FUIStorageImageLoader.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FUIStorageImageLoader.m; sourceTree = "<group>"; };
32450163224B96B400AF2E90 /* NSURL+FirebaseStorage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSURL+FirebaseStorage.h"; sourceTree = "<group>"; };
32450164224B96B400AF2E90 /* NSURL+FirebaseStorage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSURL+FirebaseStorage.m"; sourceTree = "<group>"; };
3245016B224B987400AF2E90 /* FUIStorageDefine.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FUIStorageDefine.h; sourceTree = "<group>"; };
3245016C224B987400AF2E90 /* FUIStorageDefine.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FUIStorageDefine.m; sourceTree = "<group>"; };
32A5DB2522755E480029B3D5 /* FIRStorageDownloadTask+SDWebImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FIRStorageDownloadTask+SDWebImage.h"; sourceTree = "<group>"; };
32A5DB2622755E480029B3D5 /* FIRStorageDownloadTask+SDWebImage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "FIRStorageDownloadTask+SDWebImage.m"; sourceTree = "<group>"; };
8D69E5FC21DE968300CFA49B /* FirebaseStorageUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = FirebaseStorageUI.framework; sourceTree = BUILT_PRODUCTS_DIR; };
8D69E5FF21DE968300CFA49B /* FirebaseStorageUI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FirebaseStorageUI.h; sourceTree = "<group>"; };
8D69E60021DE968300CFA49B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
Expand Down Expand Up @@ -78,6 +94,14 @@
8D69E5FF21DE968300CFA49B /* FirebaseStorageUI.h */,
8D69E61721DE96CF00CFA49B /* UIImageView+FirebaseStorage.h */,
8D69E61621DE96CF00CFA49B /* UIImageView+FirebaseStorage.m */,
3245015F224B963B00AF2E90 /* FUIStorageImageLoader.h */,
32450160224B963B00AF2E90 /* FUIStorageImageLoader.m */,
3245016B224B987400AF2E90 /* FUIStorageDefine.h */,
3245016C224B987400AF2E90 /* FUIStorageDefine.m */,
32450163224B96B400AF2E90 /* NSURL+FirebaseStorage.h */,
32450164224B96B400AF2E90 /* NSURL+FirebaseStorage.m */,
32A5DB2522755E480029B3D5 /* FIRStorageDownloadTask+SDWebImage.h */,
32A5DB2622755E480029B3D5 /* FIRStorageDownloadTask+SDWebImage.m */,
8D69E60021DE968300CFA49B /* Info.plist */,
);
path = FirebaseStorageUI;
Expand All @@ -100,6 +124,10 @@
buildActionMask = 2147483647;
files = (
8D69E61921DE96CF00CFA49B /* UIImageView+FirebaseStorage.h in Headers */,
32A5DB2722755E480029B3D5 /* FIRStorageDownloadTask+SDWebImage.h in Headers */,
32450161224B963B00AF2E90 /* FUIStorageImageLoader.h in Headers */,
3245016D224B987400AF2E90 /* FUIStorageDefine.h in Headers */,
32450165224B96B400AF2E90 /* NSURL+FirebaseStorage.h in Headers */,
8D69E60D21DE968300CFA49B /* FirebaseStorageUI.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -201,6 +229,10 @@
buildActionMask = 2147483647;
files = (
8D69E61821DE96CF00CFA49B /* UIImageView+FirebaseStorage.m in Sources */,
3245016E224B987400AF2E90 /* FUIStorageDefine.m in Sources */,
32450166224B96B400AF2E90 /* NSURL+FirebaseStorage.m in Sources */,
32450162224B963B00AF2E90 /* FUIStorageImageLoader.m in Sources */,
32A5DB2822755E480029B3D5 /* FIRStorageDownloadTask+SDWebImage.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
27 changes: 27 additions & 0 deletions Storage/FirebaseStorageUI/FIRStorageDownloadTask+SDWebImage.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//
// Copyright (c) 2019 Google Inc.
//
// 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/FirebaseStorage.h>
#import <SDWebImage/SDWebImage.h>

NS_ASSUME_NONNULL_BEGIN

// `FIRStorageDownloadTask` conforms to `SDWebImageOperation` protocol
@interface FIRStorageDownloadTask (SDWebImage) <SDWebImageOperation>

@end

NS_ASSUME_NONNULL_END
21 changes: 21 additions & 0 deletions Storage/FirebaseStorageUI/FIRStorageDownloadTask+SDWebImage.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// Copyright (c) 2019 Google Inc.
//
// 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 "FIRStorageDownloadTask+SDWebImage.h"

@implementation FIRStorageDownloadTask (SDWebImage)

@end
29 changes: 29 additions & 0 deletions Storage/FirebaseStorageUI/FUIStorageDefine.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//
// Copyright (c) 2019 Google Inc.
//
// 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/FirebaseStorage.h>
#import <SDWebImage/SDWebImage.h>

/**
* The scheme when identifing the URL is Firebase Storage URL
*/
FOUNDATION_EXPORT NSString * _Nonnull const FUIStorageScheme;

/**
* A UInt64 raw value specify the maximum size of the downloaded image. If the downloaded image
* exceeds this size, an error will be raised in the completion block. (NSNumber *)
*/
FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const FUIStorageMaxImageSize;
21 changes: 21 additions & 0 deletions Storage/FirebaseStorageUI/FUIStorageDefine.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// Copyright (c) 2019 Google Inc.
//
// 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 "FUIStorageDefine.h"

NSString * _Nonnull const FUIStorageScheme = @"gs";

SDWebImageContextOption _Nonnull const FUIStorageMaxImageSize = @"firebaseMaxImageSize";
54 changes: 54 additions & 0 deletions Storage/FirebaseStorageUI/FUIStorageImageLoader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//
// Copyright (c) 2019 Google Inc.
//
// 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 <SDWebImage/SDWebImage.h>
#import "FUIStorageDefine.h"
#import "NSURL+FirebaseStorage.h"

NS_ASSUME_NONNULL_BEGIN

/*
* This Firebase Storage loader is used to load a `Firebase Storage reference` of image record.
* To use the Firebase Storage loader, you can use the API in `UIImageView+FirebaseStorage.h` for simple usage.
* You can also use the native SDWebImage's View Category API, with the URL constructed with `FIRStorageReference`. See `NSURL+SDWebImageFIRStorageLoader.h`
* @code
// Supports HTTP URL as well as Firebase Storage URL globally. Put this in the early setup step like AppDelegate.m
SDImageLoadersManager.loaders = @[SDWebImageDownloader.sharedDownloader, SDWebImageFIRStorageLoader.sharedLoader];
// Replace default manager's loader implementation
SDWebImageManager.defaultImageLoader = SDImageLoadersManager.sharedManager;

// Then you can simply call SDWebImage's APIs the same as normal HTTP URL
FIRStorageReference *storageRef;
NSURL *url = [NSURL sd_URLWithStorageReference:storageRef];
[imageView sd_setImageWithURL:url];
* @endcode
*/
NS_SWIFT_NAME(StorageImageLoader)
@interface FUIStorageImageLoader : NSObject<SDImageLoader>

/**
* The maximum image download size, in bytes. Defaults to 10e6.
*/
@property (nonatomic, assign) UInt64 defaultMaxImageSize;

/**
The global shared instance for Firebase Storage loader.
*/
@property (nonatomic, class, readonly, nonnull) FUIStorageImageLoader *sharedLoader;

@end

NS_ASSUME_NONNULL_END
106 changes: 106 additions & 0 deletions Storage/FirebaseStorageUI/FUIStorageImageLoader.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
//
// Copyright (c) 2019 Google Inc.
//
// 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 "FUIStorageImageLoader.h"
#import "FIRStorageDownloadTask+SDWebImage.h"
#import <FirebaseCore/FirebaseCore.h>

@implementation FUIStorageImageLoader

+ (FUIStorageImageLoader *)sharedLoader {
static dispatch_once_t onceToken;
static FUIStorageImageLoader *loader;
dispatch_once(&onceToken, ^{
loader = [[FUIStorageImageLoader alloc] init];
});
return loader;
}

- (instancetype)init {
self = [super init];
if (self) {
self.defaultMaxImageSize = 10e6;
}
return self;
}

#pragma mark - SDImageLoader Protocol

- (BOOL)canRequestImageForURL:(NSURL *)url {
return url.sd_storageReference;
}

- (id<SDWebImageOperation>)requestImageWithURL:(NSURL *)url options:(SDWebImageOptions)options context:(SDWebImageContext *)context progress:(SDImageLoaderProgressBlock)progressBlock completed:(SDImageLoaderCompletedBlock)completedBlock {
FIRStorageReference *storageRef = url.sd_storageReference;
if (!storageRef) {
if (completedBlock) {
NSError *error = [NSError errorWithDomain:SDWebImageErrorDomain code:SDWebImageErrorInvalidURL userInfo:@{NSLocalizedDescriptionKey : @"The provided image url must have an associated FIRStorageReference."}];
completedBlock(nil, nil, error, YES);
}
}

UInt64 size;
if (context[FUIStorageMaxImageSize]) {
size = [context[FUIStorageMaxImageSize] unsignedLongLongValue];
} else {
size = self.defaultMaxImageSize;
}
// Download the image from Firebase Storage

// TODO: Support progressive image loading using the `GTMSessionFetcher.downloadedData` with `SDImageLoaderDecodeProgressiveImageData`
FIRStorageDownloadTask * download = [storageRef dataWithMaxSize:size
completion:^(NSData * _Nullable data, NSError * _Nullable error) {
if (error) {
dispatch_main_async_safe(^{
if (completedBlock) {
completedBlock(nil, nil, error, YES);
}
});
return;
}
// Decode the image with data
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
UIImage *image = SDImageLoaderDecodeImageData(data, url, options, context);
dispatch_main_async_safe(^{
if (completedBlock) {
completedBlock(image, data, nil, YES);
}
});
});
}];
// Observe the progress changes
[download observeStatus:FIRStorageTaskStatusProgress handler:^(FIRStorageTaskSnapshot * _Nonnull snapshot) {
NSProgress *progress = snapshot.progress;
if (progressBlock) {
progressBlock(progress.completedUnitCount, progress.totalUnitCount, url);
}
}];

return download;
}

- (BOOL)shouldBlockFailedURLWithURL:(NSURL *)url error:(NSError *)error {
if ([error.domain isEqualToString:FIRStorageErrorDomain]) {
if (error.code == FIRStorageErrorCodeBucketNotFound
|| error.code == FIRStorageErrorCodeProjectNotFound
|| error.code == FIRStorageErrorCodeObjectNotFound) {
return YES;
}
}
return NO;
}

@end
6 changes: 5 additions & 1 deletion Storage/FirebaseStorageUI/FirebaseStorageUI.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright (c) 2016 Google Inc.
// Copyright (c) 2019 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -24,3 +24,7 @@ FOUNDATION_EXPORT double FirebaseStorageUIVersionNumber;
FOUNDATION_EXPORT const unsigned char FirebaseStorageUIVersionString[];

#import "UIImageView+FirebaseStorage.h"
#import "FUIStorageImageLoader.h"
#import "FUIStorageDefine.h"
#import "NSURL+FirebaseStorage.h"
#import "FIRStorageDownloadTask+SDWebImage.h"
38 changes: 38 additions & 0 deletions Storage/FirebaseStorageUI/NSURL+FirebaseStorage.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//
// Copyright (c) 2019 Google Inc.
//
// 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 <Foundation/Foundation.h>
#import <FirebaseStorage/FirebaseStorage.h>

NS_ASSUME_NONNULL_BEGIN

@interface NSURL (FirebaseStorage)

/**
The `FIRStorageReference` value for Firebase Storage reference, or nil for other URL.
*/
@property (nonatomic, strong, readonly, nullable) FIRStorageReference *sd_storageReference;

/**
Create a Firebase Storage reference URL with `FIRStorageReference`

@param storageRef `FIRStorageReference` object
@return A Firebase Storage reference URL
*/
+ (nullable instancetype)sd_URLWithStorageReference:(nonnull FIRStorageReference *)storageRef;

@end

NS_ASSUME_NONNULL_END
Loading