This is for Firebase 6.26.0 and 6.27.0 (I've tried both for reasons that will become clear)
I have a Swift application I'm trying to decompose into modules from its current monolith, but so far I have not been able to expose Firebase classes across the modules (i.e frameworks) by installing Firebase pods in each individual module. It will only work when there is only one existing library, and when that library is installed in the application target, where it is instantiated in AppDelegate.
Does anyone know if it's possible to implement Firebase across multiple modules in a single workspace?
Expected results
That Firebase classes will be exposed to all modules in a multi-module Swift application, with one or more copies of the Firebase library present, allowing all modules to call Firebase methods and implement Firebase classes within a single, global instance of FirebaseApp.
Actual results
Either Firebase refuses to instantiate because of the presence of more than one Firebase library in the workspace, or, when only one library is present, Firebase classes cannot be exposed to other modules in the workspace.
What I've done
Installed individual Firebase pods in every module requiring them. On launch I got this error:
.
The default FirebaseApp instance must be configured before the defaultFirebaseApp instance can be initialized
.
According to an answer from a Firebase team member on another StackOverflow post, this is caused by the presence of more than one Firebase library in the workspace.Installed only one pod to create a "FirebaseProxy" module that both the application target and all other modules could share. By using typealiases and extensions I was able to let classes implement Firebase classes without having to be exposed to the actual Firebase library, for example:
import Firebase
public typealias FirebaseUserProxy = Firebase.User
public extension FirebaseUserProxy {}
So this way an implementing class could use the Firebase.User
type by using FirebaseUserProxy
instead, and without having to be directly exposed to the Firebase library.
.
However, there were some proxied classes that still seemed to require being exposed to the full library. (My brain is a bit addled from dealing with all this so I've forgotten exactly which ones, I believe it was FirebaseApp.) But even using @_exposed import Firebase
in the proxy definition didn't do the trick, and I only got the message Missing required module 'Firebase'
.
Same solution as in #2, but using
use_frameworks! :linkage => :static
in my Podfile. No luck. And yes, I did try using$(SRCROOT)/Stat
in my frameworks search paths build settings.Finally I tried integrating the library directly into my project without using Cocoapods. Here I was using 6.26.0 since the Firebase download link with a
6.27.0
in the URL resulted in aNot Found
message, so I manually changed it to6.26.0
and that downloaded fine
.
I installed the library in the application and in another module, hoping that somehow this method would obscure each library from the other, but ended up with the same error message as in #1...The default FirebaseApp...
.
I also tried using the proxy method from #2, but that resulted in the same error.
.
I had to set:linkage => :static
in my Podfile so the installed pods would play nicely with the integrated library. Turning it off resulted in an error.
Alternatives
If I can't get this to work, I may have to refactor my code so that the Firebase-dependent code exists in the application itself instead of a standalone framework module. This would not impact functionality, but it would break the architecture and make the code a good deal more convoluted and brittle.
There is a solution on the Firebase git repo (that I haven't tried), that suggests reverting back to v.6.15.0. I am reluctant to do this though since the most recent release is at 6.27.0 and I don't want to be unable to upgrade and risk using an older version that later releases will undoubtedly break eventually.
Finally
It's disappointing that such a widely used and vital tool can only be used in monolith applications, basically limiting developers to a single, often suboptimal, type of architecture. Have I missed something? Maybe. It wouldn't be the first time. But if anyone can light the way out of my dilemma I would be happy to buy you a beer, and given the current social distancing regulations, consume it on your behalf.