Adapting Compose Multiplatform for tvOS: Key Challenges and Solutions
How one developer extended Jetpack Compose to support Apple TV while maintaining cross-platform efficiency
1The multiplatform challenge
A streaming app needed to run on Android, iOS, desktop, and tvOS with a small team. Maintaining separate UI layers would be inefficient. Compose Multiplatform emerged as the solution, allowing shared UI code across platforms. However, tvOS support was missing from the framework, requiring custom implementation.
2Why SwiftUI wasn't the answer
Initial attempts to use SwiftUI for tvOS failed due to inadequate focus management. TV interfaces rely heavily on precise focus control for D-pad navigation. While Compose offers FocusRequester and interceptors, SwiftUI's limited modifiers couldn't match Android TV's behavior. This forced consideration of porting Compose to tvOS.
3tvOS technical foundations
Research revealed tvOS shares iOS's core architecture: same kernel, Objective-C runtime, UIKit, and Metal. Key differences include Siri Remote input (UIPress events), mandatory focus participation, and missing iOS APIs like drag-and-drop. The main hurdle was Kotlin/Native requiring explicit tvOS target support (tvosArm64, tvosSimulatorArm64) throughout the dependency chain.
4Critical Skiko discovery
The project's feasibility hinged on Skiko (Compose's Skia binding) supporting tvOS. Fortunately, Skiko already included tvOS targets, eliminating the need to build Skia from scratch. This discovery transformed the project from speculative to executable, saving months of potential work on low-level graphics implementation.
5Gradle plugin modifications
First changes targeted the compose-multiplatform Gradle plugin. Kotlin Multiplatform already supported tvOS, so the task involved teaching the plugin to handle tvOS resources like iOS. This required adding tvOS target checks alongside existing iOS/Mac conditions in the resource configuration logic.
6Runtime adjustments
The compose-multiplatform-core repository needed tvOS implementations for all UIKit-specific code. A dormant TV_OS platform enum was activated in ComposePlatforms.kt with a one-line change. Both tvOS targets were registered with UIKit linker flags identical to iOS configurations.
7Build system revelations
Enabling tvOS targets immediately exposed missing components: dozens of expect/actual declarations without tvOS implementations and Objective-C files incompatible with tvOS SDK. This created a clear roadmap for implementation, starting from foundational modules upward.
8Dependency-order strategy
The implementation followed module dependencies, beginning with the most fundamental Compose module. Each module was made tvOS-compatible before moving to dependent modules. This systematic approach prevented circular dependencies and ensured stable progression through the codebase.
9Focus management solutions
Critical tvOS adaptations included implementing focus restoration behaviors and D-pad navigation handlers. The existing Compose focus system (FocusRequester, focusProperties) proved adaptable to tvOS's UIKit focus engine requirements, maintaining parity with Android TV's sophisticated focus control.
10Input handling adaptations
The Siri Remote's indirect touch and press events required special handling. Unlike touchscreens, tvOS input needed translation into Compose's event system. Solutions included mapping UIPress events to appropriate Compose gestures while accounting for the trackpad's indirect input characteristics.
11API compatibility workarounds
Missing iOS APIs on tvOS (like drag-and-drop) necessitated alternative implementations or feature flags. For each incompatible API, decisions were made whether to polyfill functionality, provide tvOS-specific implementations, or gracefully degrade features unavailable on the TV platform.
12Cross-platform dividends
The effort yielded significant long-term benefits: a single UI codebase across all platforms, consistent design system implementation, and synchronized feature development. For teams supporting multiple platforms, such unification dramatically reduces maintenance overhead and accelerates iteration cycles.