1
1
# Using Core's Component System
2
2
3
3
FirebaseCore has a dependency injection system (referred to as "Interop") used to depend on
4
- functionalities provided by other Firebase SDKs. This gives the ability to depend on a typesafe
5
- interface-only API to consume without depending on the entire SDK and simulates optional
6
- dependencies - depending on the definition but not the implementing SDK and only functioning when
7
- the implementing SDK is included.
4
+ functionalities provided by other Firebase products (specifically, the frameworks that offer those
5
+ products). This gives the ability to depend on a typesafe interface-only API to consume without
6
+ depending on the entire product and simulates optional dependencies - depending on the definition
7
+ but not the product itself and only functioning when the product implementing that definition is
8
+ included.
8
9
9
10
## Table of Contents
10
11
@@ -14,20 +15,21 @@ the implementing SDK is included.
14
15
- [ Registering with Core] ( #registering-with-core )
15
16
- [ Singletons and Instance Management] ( #singletons-and-instance-management )
16
17
- [ Single Instance per ` FIRApp ` ] ( #single-instance-per-firapp )
17
- - [ SDK does not provide functionality (example: Functions)] ( #sdk -does-not-provide-functionality-(example:-functions) )
18
- - [ SDK provides functionality to other SDKs (example: Auth)] ( #sdk -provides-functionality-to-other-SDKs -(example:-auth) )
18
+ - [ Framework does not provide functionality (example: Functions)] ( #framework -does-not-provide-functionality-(example:-functions) )
19
+ - [ Framework provides functionality to other Frameworks (example: Auth)] ( #framework -provides-functionality-to-other-frameworks -(example:-auth) )
19
20
- [ Multiple Instances per FIRApp] ( #multiple-instances-per-firapp )
20
- - [ Depending on Functionality from Another SDK ] ( #depending-on-functionality-from-another-sdk )
21
+ - [ Depending on Functionality from Another Framework ] ( #depending-on-functionality-from-another-framework )
21
22
- [ Advanced Use Cases] ( #advanced-use-cases )
22
23
- [ Providing Multiple Components and Sharing Instances] ( #providing-multiple-components-and-sharing-instances )
23
24
24
25
25
26
## Overview
26
27
27
- When a Firebase SDK wants to provide functionality to another Firebase SDK, it must be done through
28
- the Interop system. Both SDKs depend on a shared protocol that describes the functionality provided
29
- by one SDK and required by the other. Let's use ` A ` and ` B ` , where ` B ` depends on functionality
30
- provided by ` A ` and the functionality is described by protocol ` AInterop ` .
28
+ When a Firebase framework wants to provide functionality to another Firebase framework, it must be
29
+ done through the Interop system. Both frameworks depend on a shared protocol in a separate framework
30
+ that describes the functionality provided by one framework and required by the other. Let's use ` A `
31
+ and ` B ` , where ` B ` depends on functionality provided by ` A ` and the functionality is described by
32
+ protocol ` AInterop ` .
31
33
32
34
During configuration, ` A ` tells Core that it provides functionality for ` AInterop ` and ` B ` tells
33
35
Core it would like functionality ` AInterop ` (and specifies whether it is required or optional) as
@@ -37,44 +39,45 @@ instantiates `B` and passes a container that contains the instance of `A` that p
37
39
` B ` has no idea what class ` A ` is, and it doesn't need to. All ` B ` needs to know is that it has an
38
40
instance of an object that conforms to ` AInterop ` and provides the functionality it needs.
39
41
40
- This system allows Firebase SDKs to depend on each other in a typesafe way and allows us to
41
- explicitly declare version dependencies on the interfaces required instead of the SDK version.
42
+ This system allows Firebase frameworks to depend on each other in a typesafe way and allows us to
43
+ explicitly declare version dependencies on the interfaces required instead of the product's version.
42
44
43
45
## Protocol Only Frameworks
44
46
45
- In order to share protocols between two SDKs , we introduced header only frameworks that declare the
46
- desired protocol(s).
47
+ In order to share protocols between two frameworks , we introduced header only frameworks that
48
+ declare the desired protocol(s).
47
49
48
- The naming convention for the framework should be ` <SDKName >Interop ` but the protocols don't have a
49
- strict naming guideline other than having a ` FIR ` prefix in Objective-C.
50
+ The naming convention for the framework should be ` <ProductName >Interop ` but the protocols don't
51
+ have a strict naming guideline other than having a ` FIR ` prefix in Objective-C.
50
52
51
- Both the implementing and dependent SDK will have a required dependency on this ` <SDKName>Interop `
52
- framework: the implementing SDK must conform to the protocols defined and register it with Core,
53
- while the dependent SDK will use the protocol definition to use methods defined by it.
53
+ Both the implementing and dependent framework will have a required dependency on this
54
+ ` <ProductName>Interop ` framework: the implementing framework must conform to the protocols defined
55
+ and register it with Core, while the dependent framework will use the protocol definition to use
56
+ methods defined by it.
54
57
55
- An Interop framework can have multiple protocols, but all should be implemented by the SDK it is
56
- named after.
58
+ An Interop framework can have multiple protocols, but all should be implemented by the product it
59
+ is named after.
57
60
58
61
Protocols * can not* declare class methods. This is an intentional decision to ensure all interfaces
59
62
interact properly based on the ` FIRApp ` that's used.
60
63
61
64
## Types and Core API
62
65
63
66
For the rest of the documentation, it's important to be familiar with the various classes and API
64
- provided by Core. Since the SDKs are written in Objective-C, we'll use the Objective-C names. The
65
- Swift names are identical but dropping the ` FIR ` prefix.
67
+ provided by Core. Since the frameworks are written in Objective-C, we'll use the Objective-C names.
68
+ The Swift names are identical but dropping the ` FIR ` prefix.
66
69
67
70
- ` @class FIRDependency `
68
71
- A dependency on a specific protocol's functionality. Created with the factory method
69
72
` [FIRDependency dependencyWithProtocol:isRequired:] `
70
73
- ` @class FIRComponent `
71
- - A component to register with Core to be consumed by other SDKs . It declares the protocol
74
+ - A component to register with Core to be consumed by other frameworks . It declares the protocol
72
75
offered, dependencies, and a block for Core to instantiate it.
73
76
- ` @class FIRComponentContainer `
74
77
- A container that holds different components that are registered with Core.
75
78
- ` @protocol FIRComponentRegistrant `
76
- - Describes functionality for SDKs registering components in the ` FIRComponentContainer ` . It
77
- allows Core to fetch components lazily from the SDK .
79
+ - Describes functionality for frameworks registering components in the ` FIRComponentContainer ` . It
80
+ allows Core to fetch components lazily from the implementing framework .
78
81
- ` #define FIR_COMPONENT(protocol, container) ` (macro)
79
82
- The macro to request an instance conforming to a given protocol from a container. Due to
80
83
Objective-C's lightweight generic system, the safest and most readable API is provided by a
@@ -83,7 +86,7 @@ Swift names are identical but dropping the `FIR` prefix.
83
86
84
87
## Registering with Core
85
88
86
- Each Firebase SDK should register with Core in the ` +load ` method of the class conforming to
89
+ Each Firebase framework should register with Core in the ` +load ` method of the class conforming to
87
90
` FIRComponentRegistrant ` . This needs to happen at ` +load ` time because Core needs to resolve any
88
91
dependencies before a class has a chance to be called by a developer (if called at all).
89
92
@@ -108,23 +111,24 @@ dependencies before a class has a chance to be called by a developer (if called
108
111
109
112
### Singletons and Instance Management
110
113
111
- All Firebase SDKs provide singleton access for convenience that map to a specific ` FIRApp ` :
112
- ` [FIRAuth auth] ` , ` [FIRFunctions functionsForApp:] ` , etc. Some SDKs can also have multiple instances
113
- per ` FIRApp ` such as Storage: ` [FIRStorage storageForApp:URL:] ` .
114
+ All Firebase frameworks provide singleton access for convenience that map to a specific ` FIRApp ` :
115
+ ` [FIRAuth auth] ` , ` [FIRFunctions functionsForApp:] ` , etc. Some frameworks can also have multiple
116
+ instances per ` FIRApp ` such as Storage: ` [FIRStorage storageForApp:URL:] ` .
114
117
115
118
These instances must be created and managed by Core through the component system. This allows the
116
119
` FIRApp ` lifecycle to control the lifecycle of instances associated with itself. There are different
117
- ways to do so depending on the SDK 's situation .
120
+ ways to do so depending on the product 's offerings .
118
121
119
122
#### Single Instance per ` FIRApp `
120
123
121
- The registration for a single instance per ` FIRApp ` changes if the SDK provides functionality to
122
- other SDKs or not.
124
+ The registration for a single instance per ` FIRApp ` changes if the framwork provides functionality
125
+ to other frameworks or not.
123
126
124
- ##### SDK does not provide functionality (example: Functions)
127
+ ##### Framework does not provide functionality (example: Functions)
125
128
126
- In this case, the SDK is a "leaf node" since no SDKs depend on it. It has a private, empty protocol
127
- that it uses to register with the container. Using Functions as an example:
129
+ In this case, the framework is a "leaf node" since no other frameworks depend on functionality from
130
+ it. It has a private, empty protocol that it uses to register with the container. Using Functions as
131
+ an example:
128
132
129
133
```
130
134
// FIRFunctions.h
@@ -144,7 +148,7 @@ that it uses to register with the container. Using Functions as an example:
144
148
}
145
149
146
150
/// The array of components to register with Core. Since Functions is a leaf node and
147
- /// doesn't provide any functionality to other SDKs , it should use Core for instance
151
+ /// doesn't provide any functionality to other frameworks , it should use Core for instance
148
152
/// management only.
149
153
+ (NSArray<FIRComponent *> *)componentsToRegister {
150
154
// Each component needs a block for Core to call in order to instantiate instances of the
@@ -185,10 +189,10 @@ that it uses to register with the container. Using Functions as an example:
185
189
@end
186
190
```
187
191
188
- ##### SDK provides functionality to other SDKs (example: Auth)
192
+ ##### Framework provides functionality to other Frameworks (example: Auth)
189
193
190
194
This example will be very similar to the one above, but let's define a simple protocol that Auth
191
- could conform to and provide to other SDKs :
195
+ could conform to and provide to other frameworks :
192
196
193
197
```
194
198
// FIRAuthInterop.h in the FirebaseAuthInterop framework.
@@ -230,7 +234,7 @@ could conform to and provide to other SDKs:
230
234
231
235
#### Multiple Instances per ` FIRApp `
232
236
233
- Instead of directly providing an instance from the container, Firestore and similar SDKs should
237
+ Instead of directly providing an instance from the container, Firestore and similar products should
234
238
create a "provider" that stores and creates instances with the required parameters. This means a
235
239
single provider per ` FIRApp ` , but multiple instances are possible per provider.
236
240
@@ -325,16 +329,16 @@ All `Firestore.m` needs to do now is call the component container from the singl
325
329
}
326
330
```
327
331
328
- ### Depending on Functionality from Another SDK
332
+ ### Depending on Functionality from Another Framework
329
333
330
334
* If you haven't already read [ Registering with Core] ( #registering-with-core ) , please do so until you
331
335
get back to this spot as it lays the groundwork necessary to understand this section.*
332
336
333
337
Adding dependencies is easy once components are registered with Core. Let's take the example from
334
338
Functions above and add a dependency to ` FIRAuthInterop ` defined above.
335
339
336
- ** Important** : You will also need to add a dependency on the ` FirebaseAuthInterop ` pod to your SDK's
337
- podspec and any package manager supported.
340
+ ** Important** : You will also need to add a dependency on the ` FirebaseAuthInterop ` pod to your
341
+ product's podspec and any package manager supported.
338
342
339
343
Before adding the dependency on ` FIRAuthInterop ` .
340
344
@@ -407,7 +411,7 @@ if (userID) {
407
411
408
412
### Providing Multiple Components and Sharing Instances
409
413
410
- Consider a situation where an SDK wants to offer functionality defined in multiple protocols
414
+ Consider a situation where a framework wants to offer functionality defined in multiple protocols
411
415
with the same instance. For example, Auth could provide ` FIRAuthUserInterop ` and
412
416
` FIRAuthSignInInterop ` . If a single Auth instance should be shared between those two protocols, the
413
417
system currently doesn't work.
0 commit comments