Skip to Content
iOS OptionsState and Lifecycle

State observation and session lifecycle

GraffityARCloud is @MainActor. Construct it and invoke view factories and synchronous controls on the main actor. From another actor, hop to the main actor for access. Configuration and state values are Sendable.

Current state and delegate

sdk.state returns a snapshot with isSceneReady, vpsState, optional navigation, and optional lastError. See state fields.

Assign a retained GraffityARCloudDelegate to sdk.delegate. Use didChangeState for snapshots and other methods for taps, collection, links, localization, and navigation events. The delegate is weak. Discrete events are not all represented in state.

Combine

New subscribers receive the current state followed by changes; duplicate snapshots are filtered. Retain the returned subscription.

import Combine import GraffityARCloud @MainActor final class SessionObserver { private var subscription: AnyCancellable? func observe(_ sdk: GraffityARCloud) { subscription = sdk.statePublisher .map(\.vpsState) .removeDuplicates() .sink { state in if case .localized(let sectionId) = state { print("Localized section: \(sectionId)") } } } func stopObserving() { subscription?.cancel() subscription = nil } }

AsyncStream

Each call creates an independent stream and immediately yields the current snapshot. Keep a task handle for cancellation.

import GraffityARCloud @MainActor func observeSession(_ sdk: GraffityARCloud) -> Task<Void, Never> { Task { @MainActor in for await state in sdk.stateStream() { if Task.isCancelled { break } if let error = state.lastError { print(error.localizedDescription) } } } }

Store the returned task and call observationTask.cancel() when ending the session. Current shutdown publishes a reset snapshot but does not finish AsyncStreams; cancel observation explicitly.

Reset localization

await sdk.reset() routes to the controller most recently created by makeViewController(). After its view loads, reset pauses AR, resets VPS, and starts AR again. It does not replace the SDK or configuration.

In 5.1.1, makeSwiftUIView() does not register its controller for this method: public reset currently has no effect for a session hosted only through SwiftUI. Use built-in retry UI or end and recreate the session. Reset before a UIKit controller loads also has no effect.

End a session

  1. Cancel your observation tasks and subscriptions.
  2. Call await sdk.shutdown().
  3. Dismiss or remove the hosted view and release its owner. For UIKit containment, call willMove(toParent: nil), remove the view, then call removeFromParent().
  4. Create a fresh configuration and SDK for the next session.

Shutdown is idempotent and makes the instance unusable. It stops the view model, tears down state bridging, and removes SDK delegate subscriptions. UIKit sessions created through the factory also receive explicit controller cleanup. For the current SwiftUI path, removing the hosted view is necessary to complete AR cleanup; shutdown alone does not reach its controller.

Keep one active hosted view per SDK. View disappearance invokes internal cleanup, but your app must still end the logical session. Do not reuse a shut-down instance or construct an SDK during each SwiftUI body evaluation.

Rejected tokens

A backend HTTP 401 reports .invalidAccessToken and triggers shutdown. There is no public in-place token rotation API. Remove the session view, obtain a new token, and construct a new session. See error handling.