Compose Multiplatform runtime library for iOS UIKit x64 target providing core runtime functionality for declarative UI framework integration.
—
Context-like data flow mechanism for passing data implicitly down the composition tree without explicit parameter passing. CompositionLocal enables sharing data across the entire composition hierarchy while maintaining type safety.
Functions for creating CompositionLocal instances with different update policies.
/**
* Creates a CompositionLocal that uses structural equality for change detection
* @param defaultFactory Optional factory for default value when no provider is found
* @return ProvidableCompositionLocal instance
*/
fun <T> compositionLocalOf(defaultFactory: (() -> T)? = null): ProvidableCompositionLocal<T>
/**
* Creates a CompositionLocal that uses referential equality for change detection
* Optimized for values that rarely change
* @param defaultFactory Optional factory for default value when no provider is found
* @return ProvidableCompositionLocal instance
*/
fun <T> staticCompositionLocalOf(defaultFactory: (() -> T)? = null): ProvidableCompositionLocal<T>Usage Examples:
// Theme CompositionLocal
val LocalAppTheme = compositionLocalOf<AppTheme> {
error("No theme provided")
}
// User CompositionLocal with default
val LocalCurrentUser = compositionLocalOf { User.guest() }
// Static CompositionLocal for rarely-changing configuration
val LocalAppConfiguration = staticCompositionLocalOf {
AppConfiguration.default()
}
data class AppTheme(
val colors: ColorScheme,
val typography: Typography,
val spacing: Spacing
)
data class User(val id: String, val name: String) {
companion object {
fun guest() = User("guest", "Guest User")
}
}Core classes and interfaces for the CompositionLocal system.
/**
* Base class for CompositionLocal providing read access
* @param T The type of value provided by this CompositionLocal
*/
abstract class CompositionLocal<T>(defaultFactory: (() -> T)?) {
/**
* Current value of this CompositionLocal in the composition
* Throws if no provider is found and no default factory was provided
*/
val current: T
@Composable get
/**
* Current value or null if no provider is found
*/
val currentOrNull: T?
@Composable get
}
/**
* CompositionLocal that can provide values to child compositions
*/
abstract class ProvidableCompositionLocal<T> : CompositionLocal<T> {
/**
* Creates a ProvidedValue for use with CompositionLocalProvider
* @param value The value to provide
* @return ProvidedValue instance
*/
infix fun provides(value: T): ProvidedValue<T>
/**
* Creates a ProvidedValue with a computed value
* @param value Function that computes the value
* @return ProvidedValue instance
*/
infix fun providesDefault(value: () -> T): ProvidedValue<T>
}
/**
* Represents a value provided to a CompositionLocal
*/
class ProvidedValue<T> internal constructor(
val compositionLocal: CompositionLocal<T>,
val value: T,
val canOverride: Boolean
)Function for providing values to CompositionLocals.
/**
* Provides values to CompositionLocals for the content lambda
* @param values Variable number of ProvidedValue instances
* @param content Composable content that can access the provided values
*/
@Composable
fun CompositionLocalProvider(
vararg values: ProvidedValue<*>,
content: @Composable () -> Unit
): UnitUsage Examples:
@Composable
fun App() {
val theme = remember { AppTheme.default() }
val user = remember { getCurrentUser() }
CompositionLocalProvider(
LocalAppTheme provides theme,
LocalCurrentUser provides user
) {
MainScreen() // Can access theme and user via CompositionLocal
}
}
@Composable
fun MainScreen() {
// Access provided values
val theme = LocalAppTheme.current
val user = LocalCurrentUser.current
Column(
modifier = Modifier.background(theme.colors.background)
) {
Text(
text = "Welcome, ${user.name}!",
style = theme.typography.headlineMedium,
color = theme.colors.onBackground
)
UserContent() // Can also access the same CompositionLocals
}
}Methods for safely accessing CompositionLocal values.
/**
* Extension property to get current value (same as .current)
*/
val <T> CompositionLocal<T>.current: T
@Composable get
/**
* Extension property to get current value or null if not provided
*/
val <T> CompositionLocal<T>.currentOrNull: T?
@Composable getUsage Examples:
@Composable
fun SafeCompositionLocalAccess() {
// Safe access with null check
val user = LocalCurrentUser.currentOrNull
if (user != null) {
Text("Hello, ${user.name}")
} else {
Text("Please log in")
}
// Direct access (throws if not provided and no default)
val theme = LocalAppTheme.current
// Using in conditional logic
val isGuest = LocalCurrentUser.currentOrNull?.id == "guest"
}@Composable
fun NestedProvidersExample() {
val lightTheme = AppTheme.light()
CompositionLocalProvider(LocalAppTheme provides lightTheme) {
Column {
Text("Light theme content")
// Override theme for specific section
val darkTheme = AppTheme.dark()
CompositionLocalProvider(LocalAppTheme provides darkTheme) {
Text("Dark theme content")
NestedContent() // Uses dark theme
}
Text("Back to light theme")
}
}
}@Composable
fun DynamicCompositionLocalExample() {
var isDarkMode by remember { mutableStateOf(false) }
val theme = if (isDarkMode) AppTheme.dark() else AppTheme.light()
CompositionLocalProvider(LocalAppTheme provides theme) {
Column {
Switch(
checked = isDarkMode,
onCheckedChange = { isDarkMode = it }
)
ThemedContent() // Automatically updates when theme changes
}
}
}// Custom scope for feature-specific data
val LocalFeatureConfig = compositionLocalOf<FeatureConfig> {
FeatureConfig.default()
}
@Composable
fun FeatureScope(
config: FeatureConfig,
content: @Composable () -> Unit
) {
CompositionLocalProvider(LocalFeatureConfig provides config) {
content()
}
}
@Composable
fun FeatureScreen() {
FeatureScope(config = FeatureConfig.forUser(currentUser)) {
FeatureContent() // Can access LocalFeatureConfig
}
}// iOS-specific configuration
val LocalIOSConfiguration = compositionLocalOf<IOSConfiguration> {
error("iOS configuration not provided")
}
val LocalUIViewController = compositionLocalOf<UIViewController?> { null }
data class IOSConfiguration(
val statusBarStyle: UIStatusBarStyle,
val interfaceOrientation: UIInterfaceOrientation,
val safeAreaInsets: EdgeInsets
)
@Composable
fun IOSApp(viewController: UIViewController) {
val iosConfig = remember {
IOSConfiguration(
statusBarStyle = UIStatusBarStyle.default,
interfaceOrientation = UIInterfaceOrientation.portrait,
safeAreaInsets = viewController.view.safeAreaInsets.toEdgeInsets()
)
}
CompositionLocalProvider(
LocalUIViewController provides viewController,
LocalIOSConfiguration provides iosConfig
) {
AppContent()
}
}@Composable
fun UIKitIntegrationExample() {
val viewController = LocalUIViewController.currentOrNull
val iosConfig = LocalIOSConfiguration.current
LaunchedEffect(iosConfig.statusBarStyle) {
viewController?.setNeedsStatusBarAppearanceUpdate()
}
// Use iOS configuration in Composable
Column(
modifier = Modifier.padding(iosConfig.safeAreaInsets)
) {
// Content respects safe area insets
}
}@Composable
fun TransformCompositionLocalExample() {
val baseTheme = LocalAppTheme.current
// Create derived theme
val dialogTheme = remember(baseTheme) {
baseTheme.copy(
colors = baseTheme.colors.copy(
surface = baseTheme.colors.surfaceVariant
)
)
}
CompositionLocalProvider(LocalAppTheme provides dialogTheme) {
DialogContent() // Uses modified theme
}
}@Composable
fun ConditionalProvisionExample(user: User?) {
if (user != null) {
CompositionLocalProvider(LocalCurrentUser provides user) {
AuthenticatedContent()
}
} else {
UnauthenticatedContent() // LocalCurrentUser not provided
}
}@Composable
fun MultipleProvidersExample() {
val adminTheme = AppTheme.admin()
val userTheme = AppTheme.user()
Row {
CompositionLocalProvider(LocalAppTheme provides adminTheme) {
AdminPanel()
}
CompositionLocalProvider(LocalAppTheme provides userTheme) {
UserPanel()
}
}
}staticCompositionLocalOf for rarely-changing values to optimize recompositionInstall with Tessl CLI
npx tessl i tessl/maven-org-jetbrains-compose-runtime--runtime-uikitx64