KMPCharts/samples/ios/ChartRealtimeDemo
Trentin Davide 07197ed8df
Some checks are pending
CI / build (push) Waiting to run
chore(portfolio): v1.0.0 prep — docs, CI, demos
Autonomous portfolio prep batch. All gates green: 207 tests pass on
iosSimulatorArm64Test, assembleRelease green, apiCheck green, app builds.

Docs:
- CHANGELOG.md (Keep-a-Changelog, retroactive v0.1-v0.5)
- CONTRIBUTING.md (build + style + PR workflow + perf rules)
- chart-realtime/README.md rewrite for v0.5.0 API surface
- docs/PERFORMANCE.md (LoD perf table, alloc budget, memory budget,
  stability report, threading model)

CI (.github/):
- workflows/ci.yml — macos-latest, JDK 21, konan cache, full gate
- workflows/release.yml — tag-triggered, GitHub release with XCFramework
  + AAR; Maven Central as commented TODO (needs OSSRH + GPG secrets)
- dependabot.yml — weekly gradle + actions updates
- pull_request_template.md + 2 issue templates (bug, feature)

Android demo polish:
- DemoScreen + ControlPanel (Material3 surface)
- Sample rate slider (10..200Hz), 1-6 signal count, per-signal waveform
  picker (sine/square/triangle/noise), window seconds, LoD picker, Y
  label mode, Y formatter, interaction toggle, theme switch, status chips
- Single producer coroutine (cleaner crosshair readout, easier rate
  accounting)
- SignalGenerator + WaveformType + DemoConfig + PushCounter

iOS demo scaffold (samples/ios/ChartRealtimeDemo/):
- SPM Package.swift with local binaryTarget pointing to
  chart-realtime/build/XCFrameworks/debug/ChartRealtime.xcframework
- DemoApp.swift + DemoView.swift (smoke test confirming Kotlin types
  accessible from Swift)
- README documents the ComposeUIViewController shim needed in
  chart-realtime/src/iosMain/ for full SwiftUI hosting (deferred to
  v1.0.0 T1)
- xcodebuild against iOS Simulator builds green

Debt:
- gradle.properties: removed kotlin.internal.klibs.non-packed=false
  (Compose-MP 1.11.0 final no longer needs the bypass; apiCheck +
  native compile + 207 tests still green)
- 8 remaining deprecation warnings tied to com.android.library + KMP
  plugin combo; clearing them requires migration to
  com.android.kotlin.multiplatform.library 9.2.0 which forces ABI
  baseline regen + Maven publish restructure + XCFramework hierarchy
  expansion. Deferred as dedicated ticket.

Skipped (need user):
- CODE_OF_CONDUCT.md (content classifier blocks Contributor Covenant
  verbatim)
- Maven Central T1 (Sonatype + GPG)
- Benchmark vs competitors T4 (methodology + Maven coords)
- Logo/banner/GIF T7 (design assets)
- Tag + GitHub release T10 (rename pending)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 10:54:26 +02:00
..
Sources/ChartRealtimeDemo chore(portfolio): v1.0.0 prep — docs, CI, demos 2026-05-22 10:54:26 +02:00
.gitignore chore(portfolio): v1.0.0 prep — docs, CI, demos 2026-05-22 10:54:26 +02:00
Package.swift chore(portfolio): v1.0.0 prep — docs, CI, demos 2026-05-22 10:54:26 +02:00
README.md chore(portfolio): v1.0.0 prep — docs, CI, demos 2026-05-22 10:54:26 +02:00

ChartRealtime iOS Demo

SwiftUI app consuming ChartRealtime.xcframework via Swift Package Manager.

Build

Prerequisites:

  • Xcode 15+
  • macOS on Apple Silicon (Intel Mac simulators are NOT supported since v0.5.0)
  • Local ChartRealtime.xcframework built via Gradle

From the repo root:

./gradlew :chart-realtime:assembleChartRealtimeDebugXCFramework

This produces:

chart-realtime/build/XCFrameworks/debug/ChartRealtime.xcframework

The Package.swift references it via a local binaryTarget:

.binaryTarget(
    name: "ChartRealtime",
    path: "../../../chart-realtime/build/XCFrameworks/debug/ChartRealtime.xcframework"
)

Then resolve + build the SPM package:

cd samples/ios/ChartRealtimeDemo
swift package resolve
swift build

To run the app, open the package in Xcode (File > Open... > Package.swift) or wrap it in a thin app target. A standalone xcodeproj is intentionally NOT shipped in this scaffold.

Current limitation

chart-realtime exposes the @Composable fun RealtimeChart composable, but it does NOT yet export a ComposeUIViewController factory wrapping it into a plain UIViewController suitable for SwiftUI hosting.

Until that bridge ships (planned for v1.0.0 T1), this demo:

  • Verifies the XCFramework is consumable from Swift via SPM binaryTarget
  • Instantiates the full Kotlin-side public API (RealtimeChartState, ChartConfig, DataConfig, AxisConfig, RenderConfig, MinMaxLttbLodStrategy, TimeAxisFormatter, DecimalAxisFormatter, YRange.Auto, T0.FirstSample, FrameRate.Display, LineSignalRenderer, SignalConfig, ChartTheme) from SwiftUI
  • Registers a signal via state.addSignal(name:signalConfig:)
  • Does NOT render the actual chart

Enabling the full demo (post-v1.0.0 T1)

In chart-realtime/src/iosMain/:

import androidx.compose.ui.window.ComposeUIViewController
import platform.UIKit.UIViewController

public fun RealtimeChartViewController(
    state: RealtimeChartState,
    xWindowSeconds: Float = state.config.data.xWindowSeconds,
): UIViewController = ComposeUIViewController {
    RealtimeChart(state = state, xWindowSeconds = xWindowSeconds)
}

Then in SwiftUI:

import SwiftUI
import ChartRealtime
import UIKit

struct ChartHost: UIViewControllerRepresentable {
    let state: RealtimeChartState

    func makeUIViewController(context: Context) -> UIViewController {
        // Kotlin top-level functions are exposed under the Kt-suffixed class
        // in the auto-generated ObjC header; exact symbol depends on file name.
        return RealtimeChartViewControllerKt.RealtimeChartViewController(
            state: state,
            xWindowSeconds: 10.0
        )
    }

    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}
}

ObjC bridge gotchas observed while authoring this demo

  • All Kotlin data-class constructors lose default arguments when crossing the ObjC bridge — callers must pass every constructor argument explicitly.
  • Sealed-class objects (YRange.Auto, T0.FirstSample, FrameRate.Display) are exposed as classes with no-arg init(). Use YRange.Auto(), etc.
  • Compose Color is bridged as uint64_t (Kotlin ULong) — pass raw ARGB packed values: 0xFF00FF88 for opaque mint green.
  • LineSignalRenderer is a Kotlin object (singleton) — both LineSignalRenderer() and LineSignalRenderer.shared work in Swift.
  • dataVersion is currently not exposed as a Swift-visible property of RealtimeChartState (it is a Compose MutableState<Int> not flattened by Kotlin/Native ObjC export). A var dataVersionInt: Int getter would help.

Files

  • Package.swift — SPM manifest, links ChartRealtime.xcframework via local binaryTarget
  • Sources/ChartRealtimeDemo/DemoApp.swift — SwiftUI @main entry point
  • Sources/ChartRealtimeDemo/DemoView.swift — placeholder view + Kotlin smoke test