Skip to content

SwiftUI Frontend

MeroKitUI is an optional SwiftUI layer that ships alongside the core SDK — an @MainActor observable MeroClient plus ready-made views. It’s the native analog of mero-react’s MeroProvider/useMero + LoginModal: wire it in and you get login → home routing on auth state for free.

import MeroKit // core SDK
import MeroKitUI // SwiftUI frontend

(Add the MeroKitUI library product alongside MeroKit — see install.)

MeroRootView routes between LoginView and HomeView based on client.isAuthenticated. Inject a MeroClient via .environmentObject:

import MeroKitUI
import SwiftUI
@main
struct MyApp: App {
@StateObject private var client = MeroClient()
var body: some Scene {
WindowGroup {
MeroRootView(callbackScheme: "myapp") // Cloud sign-in ⇄ Home
.environmentObject(client)
}
}
}
MeroClient@MainActor ObservableObject · @Published isAuthenticatedMeroRootViewroutes on client.isAuthenticatedenvironmentObjectfalseLoginViewnode URL · username · password→ signInWithCloud(…)trueHomeViewsession info · run demo RPC→ client.logout()

An @MainActor public final class MeroClient: ObservableObject wrapping a Mero. Bind its published state directly in your own views.

Published state (read-only from views):

@Published public private(set) var isAuthenticated: Bool
@Published public private(set) var isLoading: Bool
@Published public private(set) var nodeURL: String
@Published public private(set) var username: String
@Published public private(set) var errorMessage: String?
@Published public private(set) var lastRpcResult: String?
// Cloud session
@Published public private(set) var account: String?
@Published public private(set) var relayURL: String?
@Published public private(set) var isSignedInWithoutRelay: Bool
@Published public private(set) var cloudNote: String?
public private(set) var connection: CloudConnection?

Methods (errors surface via errorMessage, so these don’t throw):

public init(session: URLSession? = nil,
tokenStore: @escaping @Sendable () -> any TokenStore = { MemoryTokenStore() },
cloud: CloudSignIn? = nil, // Keychain-backed by default
webAuthenticator: (any WebAuthenticating)? = nil) // the system auth sheet by default
func signInWithCloud(callbackScheme: String) async // e.g. "myapp" → myapp://enrol
func signInWithCloud(callback: CloudCallback) async // .https(host:path:) for a Universal Link
func handleEnrolmentCallback(_ url: URL) async -> Bool
func restoreCloudSession() async -> Bool
func login(nodeURL: String, username: String, password: String) async // development nodes only
func runSampleRpc(contextId: String, method: String) async
func logout() async

Use it in your own SwiftUI view without the bundled screens:

struct SignInView: View {
@EnvironmentObject private var client: MeroClient
var body: some View {
VStack {
Button("Continue with Calimero") {
Task { await client.signInWithCloud(callbackScheme: "myapp") }
}
if let error = client.errorMessage { Text(error).foregroundStyle(.red) }
}
.disabled(client.isLoading)
}
}

All three are public Views that read the MeroClient from @EnvironmentObject:

View Purpose
MeroRootView(callbackScheme:) restores a stored session; routes LoginView ⇄ HomeView; handles onOpenURL
LoginView(callbackScheme:) one “Continue with Calimero” button → client.signInWithCloud(...)
HomeView(demoContextId:demoMethod:) signed-in screen: session info, demo RPC, logout