The skip-firebase framework is available at https://github.com/skiptools/skip-firebase.git, which can be checked out and tested with skip test
once Skip is installed.
SkipFirebase
- TOC
This package provides Firebase support for Skip app/framework projects.
The Swift side uses the official Firebase iOS SDK directly,
with the various SkipFirebase*
modules passing the transpiled calls
through to the Firebase Android SDK.
For an example of using Firebase in a Skip app, see the Fireside Sample.
Package
An example of a Skip app projects using the Firestore
and Messaging
API can be seen
from the command:
skip init --show-tree --icon-color='1abc9c' --no-zero --appid=skip.fireside.App --version 0.0.1 skipapp-fireside FireSide:skip-ui/SkipUI FireSideModel:skip-foundation/SkipFoundation:skip-model/SkipModel:skip-firebase/SkipFirebaseFirestore:skip-firebase/SkipFirebaseMessaging:skip-firebase/SkipFirebaseAuth
This will create an SwiftPM project in skipapp-fireside/Package.swift
like:
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "skipapp-fireside",
defaultLocalization: "en",
platforms: [.iOS(.v16), .macOS(.v13), .tvOS(.v16), .watchOS(.v9), .macCatalyst(.v16)],
products: [
.library(name: "FireSideApp", type: .dynamic, targets: ["FireSide"]),
.library(name: "FireSideModel", targets: ["FireSideModel"]),
],
dependencies: [
.package(url: "https://source.skip.tools/skip.git", from: "0.7.42"),
.package(url: "https://source.skip.tools/skip-ui.git", from: "0.0.0"),
.package(url: "https://source.skip.tools/skip-foundation.git", from: "0.0.0"),
.package(url: "https://source.skip.tools/skip-model.git", from: "0.0.0"),
.package(url: "https://source.skip.tools/skip-firebase.git", from: "0.0.0")
],
targets: [
.target(name: "FireSide", dependencies: [
"FireSideModel",
.product(name: "SkipFoundation", package: "skip-foundation"),
.product(name: "SkipUI", package: "skip-ui")
], resources: [.process("Resources")], plugins: [.plugin(name: "skipstone", package: "skip")]),
.testTarget(name: "FireSideTests", dependencies: [
"FireSide",
.product(name: "SkipTest", package: "skip")
], resources: [.process("Resources")], plugins: [.plugin(name: "skipstone", package: "skip")]),
.target(name: "FireSideModel", dependencies: [
.product(name: "SkipFoundation", package: "skip-foundation"),
.product(name: "SkipModel", package: "skip-model"),
.product(name: "SkipFirebaseFirestore", package: "skip-firebase"),
.product(name: "SkipFirebaseMessaging", package: "skip-firebase"),
.product(name: "SkipFirebaseAuth", package: "skip-firebase")
], resources: [.process("Resources")], plugins: [.plugin(name: "skipstone", package: "skip")]),
.testTarget(name: "FireSideModelTests", dependencies: [
"FireSideModel",
.product(name: "SkipTest", package: "skip")
], resources: [.process("Resources")], plugins: [.plugin(name: "skipstone", package: "skip")]),
]
)
Usage
For a Skip app, the simplest way to setup Firebase support is to
create a Firebase project at https://console.firebase.google.com/project.
Follow the Firebase setup instructions to obtain the
GoogleService-Info.plist
and google-services.json
files and
add them to the iOS and Android sides of the project.
You will then be able to access the singleton type for each of the imported Firebase modules, like so:
Common Errors
Error in adb logcat: FirebaseApp: Default FirebaseApp failed to initialize because no default options were found.
This usually means that com.google.gms:google-services was not applied to your gradle project.
The app’s com.google.gms:google-services
plugin must be applied to the build.gradle.kts
file for the app’s target.
Testing
For unit testing, where there isn’t a standard place to store the
GoogleService-Info.plist
and google-services.json
configuration files,
you can create an configure the app using the SkipFirebaseCore.FirebaseApp
API manually from the information provided from the Firebase console, like so:
import SkipFirebaseCore
import SkipFirebaseAuth
import SkipFirebaseStorage
import SkipFirebaseDatabase
import SkipFirebaseAppCheck
import SkipFirebaseFunctions
import SkipFirebaseFirestore
import SkipFirebaseMessaging
import SkipFirebaseCrashlytics
import SkipFirebaseRemoteConfig
import SkipFirebaseInstallations
let appName = "myapp"
let options = FirebaseOptions(googleAppID: "1:GCM:ios:HASH", gcmSenderID: "GCM")
options.projectID = "some-firebase-projectid"
options.storageBucket = "some-firebase-demo.appspot.com"
options.apiKey = "some-api-key"
FirebaseApp.configure(name: appName, options: options)
guard let app = FirebaseApp.app(name: appName) else {
fatalError("Cannot load Firebase config")
}
// customize the app here
app.isDataCollectionDefaultEnabled = false
// use the app to create and test services
let auth = Auth.auth(app: app)
let storage = Storage.storage(app: app)
let database = Database.database(app: app)
let appcheck = AppCheck.appCheck(app: app)
let functions = Functions.functions(app: app)
let firestore = Firestore.firestore(app: app)
let crashlytics = Crashlytics.crashlytics(app: app)
let remoteconfig = RemoteConfig.remoteConfig(app: app)
let installations = Installations.installations(app: app)
Package
The modules in the SkipFirebase framework project mirror the division of the SwiftPM modules in the Firebase iOS SDK (at https://github.com/firebase/firebase-ios-sdk), which is also mirrored in the division of the Firebase Kotlin Android gradle modules (at https://github.com/firebase/firebase-android-sdk).
The individual modules of the SkipFirebase framework are as follows:
SkipFirebaseCore
Provides Skip parity to the FirebaseApp API for the Swift and Kotlin sides of the Firebase API.
Example usage:
#if !SKIP
import FirebaseCore
#else
import SkipFirebaseCore
#endif
// use the default FirebaseApp configured for the app
let app: FirebaseApp? = FirebaseApp.app()
// …or use create a customized FirebaseApp
let options = FirebaseOptions(googleAppID: "1:GCM:ios:HASH", gcmSenderID: "GCM")
options.projectID = "some-firebase-projectid"
options.storageBucket = "some-firebase-demo.appspot.com"
options.apiKey = "some-api-key"
FirebaseApp.configure(name: appName, options: options)
guard let app = FirebaseApp.app(name: appName) else {
fatalError("Cannot load Firebase config")
}
SkipFirebaseFirestore
Provides rudimentary Skip parity to the FirebaseFirestore API for the Swift and Kotlin sides of the Firebase API.
Example usage:
#if !SKIP
import FirebaseFirestore
#else
import SkipFirebaseFirestore
#endif
let firestore = Firestore.firestore()
let result = try await firestore.update()
Preview Modules
The following modules will compile, but no API parity is provided yet. Please consider opening an issue or pull request if an implementation of any of these modules is needed.
SkipFirebaseAnalytics
Provides rudimentary Skip parity to the FirebaseAnalytics API for the Swift and Kotlin sides of the Firebase API.
Example usage:
#if !SKIP
import FirebaseAnalytics
#else
import SkipFirebaseAnalytics
#endif
Analytics.logEvent("event_name", parameters: ["key": "value"])
SkipFirebaseAppCheck
Provides rudimentary Skip parity to the FirebaseAppCheck API for the Swift and Kotlin sides of the Firebase API.
Example usage:
#if !SKIP
import FirebaseAppCheck
#else
import SkipFirebaseAppCheck
#endif
let appcheck = AppCheck.appCheck()
let result = try await appcheck.update()
SkipFirebaseAuth
Provides rudimentary Skip parity to the FirebaseAuth API for the Swift and Kotlin sides of the Firebase API.
Example usage:
#if !SKIP
import FirebaseAuth
#else
import SkipFirebaseAuth
#endif
let auth = Auth.auth()
let result = try await auth.update()
SkipFirebaseCrashlytics
Provides rudimentary Skip parity to the FirebaseCrashlytics API for the Swift and Kotlin sides of the Firebase API.
Example usage:
#if !SKIP
import FirebaseCrashlytics
#else
import SkipFirebaseCrashlytics
#endif
let crashlytics = Crashlytics.crashlytics()
let result = try await crashlytics.update()
SkipFirebaseDatabase
Provides rudimentary Skip parity to the FirebaseDatabase API for the Swift and Kotlin sides of the Firebase API.
Example usage:
#if !SKIP
import FirebaseDatabase
#else
import SkipFirebaseDatabase
#endif
let database = Database.database()
let result = try await database.update()
SkipFirebaseFunctions
Provides rudimentary Skip parity to the FirebaseFunctions API for the Swift and Kotlin sides of the Firebase API.
Example usage:
#if !SKIP
import FirebaseFunctions
#else
import SkipFirebaseFunctions
#endif
let functions = Functions.functions()
let result = try await functions.update()
SkipFirebaseInstallations
Provides rudimentary Skip parity to the FirebaseInstallations API for the Swift and Kotlin sides of the Firebase API.
Example usage:
#if !SKIP
import FirebaseInstallations
#else
import SkipFirebaseInstallations
#endif
let installations = Installations.installations()
let result = try await installations.update()
SkipFirebaseMessaging
Provides rudimentary Skip parity to the FirebaseMessaging API for the Swift and Kotlin sides of the Firebase API.
Example usage:
#if !SKIP
import FirebaseMessaging
#else
import SkipFirebaseMessaging
#endif
let messaging = Messaging.messaging()
// not yet implemented in Skip
messaging.token { token, error in
if let error = error {
print("Error fetching FCM registration token: \(error)")
} else if let token = token {
print("FCM registration token: \(token)")
// Here you can send the token to your server and store it for future use
}
}
let result = try await messaging.update()
SkipFirebaseRemoteConfig
Provides rudimentary Skip parity to the FirebaseRemoteConfig API for the Swift and Kotlin sides of the Firebase API.
Example usage:
#if !SKIP
import FirebaseRemoteConfig
#else
import SkipFirebaseRemoteConfig
#endif
let remoteconfig = RemoteConfig.remoteConfig()
let result = try await remoteconfig.update()
SkipFirebaseStorage
Provides rudimentary Skip parity to the FirebaseStorage API for the Swift and Kotlin sides of the Firebase API.
Example usage:
#if !SKIP
import FirebaseStorage
#else
import SkipFirebaseStorage
#endif
let storage = Storage.storage()
let result = try await storage.update()
Building
This project is a free Swift Package Manager module that uses the Skip plugin to transpile Swift into Kotlin.
Building the module requires that Skip be installed using
Homebrew with brew install skiptools/skip/skip
.
This will also install the necessary build prerequisites:
Kotlin, Gradle, and the Android build tools.
Testing
The module can be tested using the standard swift test
command
or by running the test target for the macOS destination in Xcode,
which will run the Swift tests as well as the transpiled
Kotlin JUnit tests in the Robolectric Android simulation environment.
Parity testing can be performed with skip test
,
which will output a table of the test results for both platforms.