Skip to content

Commit 6a769f2

Browse files
Cache FirebaseStorage instances (#8178)
1 parent af49dfb commit 6a769f2

File tree

4 files changed

+48
-9
lines changed

4 files changed

+48
-9
lines changed

FirebaseStorage/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# Unreleased (8.1.0)
2+
- [changed] Instances are now cached. Repeated invocations of `Storage.storage()`
3+
return the same instance and retain the same settings.
4+
15
# 8.0.0
26
- [added] Added `FirebaseStorage.useEmulator()`, which allows the Storage SDK to
37
connect to the Cloud Storage for Firebase emulator.

FirebaseStorage/Sources/FIRStorageComponent.m

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222

2323
NS_ASSUME_NONNULL_BEGIN
2424

25+
/** A NSMutableDictionary of FirebaseApp name and bucket names to FIRStorage instance. */
26+
typedef NSMutableDictionary<NSString *, FIRStorage *> FIRStorageDictionary;
27+
2528
@interface FIRStorage ()
2629
// Surface the internal initializer to create instances of FIRStorage.
2730
- (instancetype)initWithApp:(FIRApp *)app
@@ -31,6 +34,7 @@ - (instancetype)initWithApp:(FIRApp *)app
3134
@end
3235

3336
@interface FIRStorageComponent () <FIRLibrary>
37+
@property(nonatomic) FIRStorageDictionary *instances;
3438
/// Internal initializer.
3539
- (instancetype)initWithApp:(FIRApp *)app;
3640
@end
@@ -43,6 +47,7 @@ - (instancetype)initWithApp:(FIRApp *)app {
4347
self = [super init];
4448
if (self) {
4549
_app = app;
50+
_instances = [NSMutableDictionary dictionary];
4651
}
4752
return self;
4853
}
@@ -60,6 +65,7 @@ + (void)load {
6065
isRequired:NO];
6166
FIRComponentCreationBlock creationBlock =
6267
^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) {
68+
*isCacheable = YES;
6369
return [[FIRStorageComponent alloc] initWithApp:container.app];
6470
};
6571
FIRComponent *storageProvider =
@@ -74,10 +80,21 @@ + (void)load {
7480
#pragma mark - FIRStorageInstanceProvider Conformance
7581

7682
- (FIRStorage *)storageForBucket:(NSString *)bucket {
77-
// Create an instance of FIRStorage and return it.
78-
id<FIRAuthInterop> auth = FIR_COMPONENT(FIRAuthInterop, self.app.container);
79-
id<FIRAppCheckInterop> appCheck = FIR_COMPONENT(FIRAppCheckInterop, self.app.container);
80-
return [[FIRStorage alloc] initWithApp:self.app bucket:bucket auth:auth appCheck:appCheck];
83+
FIRStorageDictionary *instances = [self instances];
84+
@synchronized(instances) {
85+
FIRStorage *instance = instances[bucket];
86+
if (!instance) {
87+
// Create an instance of FIRStorage and return it.
88+
id<FIRAuthInterop> auth = FIR_COMPONENT(FIRAuthInterop, self.app.container);
89+
id<FIRAppCheckInterop> appCheck = FIR_COMPONENT(FIRAppCheckInterop, self.app.container);
90+
instance = [[FIRStorage alloc] initWithApp:self.app
91+
bucket:bucket
92+
auth:auth
93+
appCheck:appCheck];
94+
instances[bucket] = instance;
95+
}
96+
return instance;
97+
}
8198
}
8299

83100
@end

FirebaseStorage/Tests/Integration/FIRStorageIntegrationTests.m

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,24 @@ - (void)tearDown {
137137
[super tearDown];
138138
}
139139

140+
- (void)testSameInstanceNoBucket {
141+
FIRStorage *storage1 = [FIRStorage storageForApp:self.app];
142+
FIRStorage *storage2 = [FIRStorage storageForApp:self.app];
143+
XCTAssertEqual(storage1, storage2);
144+
}
145+
146+
- (void)testSameInstanceCustomBucket {
147+
FIRStorage *storage1 = [FIRStorage storageForApp:self.app URL:@"gs://foo-bar.appspot.com"];
148+
FIRStorage *storage2 = [FIRStorage storageForApp:self.app URL:@"gs://foo-bar.appspot.com"];
149+
XCTAssertEqual(storage1, storage2);
150+
}
151+
152+
- (void)testDiffferentInstance {
153+
FIRStorage *storage1 = [FIRStorage storageForApp:self.app];
154+
FIRStorage *storage2 = [FIRStorage storageForApp:self.app URL:@"gs://foo-bar.appspot.com"];
155+
XCTAssertNotEqual(storage1, storage2);
156+
}
157+
140158
- (void)testName {
141159
NSString *aGSURI = [NSString
142160
stringWithFormat:@"gs://%@.appspot.com/path/to", [[FIRApp defaultApp] options].projectID];

FirebaseStorage/Tests/Unit/FIRStorageComponentTests.m

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ - (void)testStorageInstanceCreation {
5656
XCTAssertNotNil(storage);
5757
}
5858

59-
/// Tests that the component container does not cache instances of FIRStorageComponent.
59+
/// Tests that the component container caches instances of FIRStorageComponent.
6060
- (void)testMultipleComponentInstancesCreated {
6161
// App isn't used in any of this, so a simple class mock works for simplicity.
6262
id app = OCMClassMock([FIRApp class]);
@@ -71,8 +71,8 @@ - (void)testMultipleComponentInstancesCreated {
7171
FIR_COMPONENT(FIRStorageMultiBucketProvider, container);
7272
XCTAssertNotNil(provider2);
7373

74-
// Ensure they're different instances.
75-
XCTAssertNotEqual(provider1, provider2);
74+
// Ensure they're the same instance.
75+
XCTAssertEqual(provider1, provider2);
7676
}
7777

7878
/// Tests that instances of FIRStorage created are different.
@@ -92,8 +92,8 @@ - (void)testMultipleStorageInstancesCreated {
9292
FIRStorage *storage2 = [provider storageForBucket:@"randomBucket"];
9393
XCTAssertNotNil(storage2);
9494

95-
// Ensure that they're different instances but equal objects since everything else matches.
96-
XCTAssertNotEqual(storage1, storage2);
95+
// Ensure that they're the same instance
96+
XCTAssertEqual(storage1, storage2);
9797
XCTAssertEqualObjects(storage1, storage2);
9898

9999
// Create another bucket with a different provider from above.

0 commit comments

Comments
 (0)