Skip to content

Instantly share code, notes, and snippets.

@codesplode
Last active May 20, 2023 00:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save codesplode/c0f89ca760786361020aa23250d551dc to your computer and use it in GitHub Desktop.
Save codesplode/c0f89ca760786361020aa23250d551dc to your computer and use it in GitHub Desktop.
import KeychainAccess
import shared
class CredentialService : PlatformCredentialService {
private let keychain: Keychain
public init(_ id: String) {
keychain = Keychain(service: id)
}
public override func getString(key: String) -> String? {
try? keychain.getString(key) ?? nil
}
public override func setString(key: String, value: String?) {
if (value == nil) {
try? keychain.remove(key)
} else {
try? keychain.set(value!, key: key)
}
}
public override func clear() {
try? keychain.removeAll()
}
}
object PlatformSpecificServices() {
lateinit var credentialService: PlatformCredentialService
lateinit var locationService: PlatformLocationService
}
abstract class PlatformCredentialService {
/**
* Platform required implementation for getting a credential value.
* @return The value or null if the credential does not exist.
*/
abstract fun getString(name: String): String?
/**
* Platform required implementation for setting a credential value.
* A value of null clears the credential.
*/
abstract fun setString(name: String, value: String?)
/**
* Platform required implementation for clearing all values.
*/
abstract fun clear()
/*
* Methods implemented in Kotlin, that hide the complexity and reduce the need for other platfrom specific methods.
*/
fun containsKey(name: String): Bool = getCredential(name) != null
fun remove(name: String) {
setString(name, null)
}
}
abstract class PlatformLocationService {
/**
* Platform required implementation for updating the user's location.
*/
abstract fun updateLocation(latitude: Double, longitude: Double, time: Long, speed: Double, bearing: Double)
/*
* Methods implemented in Kotlin, that hide the complexity and reduce the need for other platfrom specific methods.
*/
fun getHistory(since: Long): List<YourLocationObject> {
// Your shared code here
}
}
import shared
import SwiftUI
@main
struct YourApp: Themeable, App {
@ObservedViewModel private var model: AppViewModel = {
KoinKt.doInitKoin()
// Set the platform services to your platform specific implementations
let platformServices: PlatformSpecificServices = koin.get()
platformServices.credentialService = CredentialService("yourapp.keycainServiceId")
platformServices.locationService = LocationService()
return koin.get()
}()
var body: some Scene {
WindowGroup {
ZStack {
// Your UI Here
}
}
}
}
@codesplode
Copy link
Author

Note that Swift does not like Kotlin defaulted arguments and overrides on those so best to avoid those in these APIs. The CredentialService swift implementation is actually based on working code using the KeychainAccess swift package at https://github.com/kishikawakatsumi/KeychainAccess

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment