SwiftCrossUI

repository·main·Indexed 23 days ago

https://github.com/moreswift/swift-cross-ui

A SwiftUI-like framework for creating cross-platform applications using Swift (5.10+). It enables developers to write code once and render it natively across macOS, Windows, Linux, iOS, and tvOS using various backends including AppKit, WinUI, Gtk, and UIKit.

Tokens
14.1K
Snippets
18
Records
84
Agent score
82%

What's inside SwiftCrossUI

  1. Overview of SwiftCrossUI example apps

    main

    SwiftCrossUI includes several example applications designed to demonstrate specific features and APIs:

    • MusicPlayerExample: Offline music player with playlist persistence.
    • CounterExample: Basic state management with increment/decrement buttons.
    • RandomNumberGeneratorExample: Simple range-based random number generation.
    • WindowingExample: Demonstrates WindowGroup, multi-window apps, and modals (alerts, sheets, file pickers).
    • GreetingGeneratorExample: Demonstrates dynamic state and the ForEach view.
    • NavigationExample: Showcases NavigationStack and related navigation concepts.
    • SplitExample: Showcases hierarchical navigation using NavigationSplitView.
    • StressTestExample: Tests view update performance.
    • SpreadsheetExample: Demonstrates table usage.
    • ControlsExample: Showcases various available UI controls.
    • NotesExample: Demonstrates multi-line text editing and realistic app usage.
    • PathsExample: Demonstrates drawing shapes using Path.
    • WebViewExample: Showcases WebView (Note: Currently only works on Apple platforms).
    • AdvancedCustomizationExample: Demonstrates advanced APIs for customizing underlying native views.
  2. Understand the new AppBackend protocol hierarchy

    main

    The AppBackend protocol has been refactored into a modular system organized within the BackendFeatures namespace. Instead of one massive protocol, features are now split into smaller, composable protocols. This allows backends to implement only what they support, and features are now optional.

    There are three core top-level protocol compositions that backend developers should use:

    1. BackendFeatures.Core: The bare minimum required for a SwiftCrossUI app to launch without crashing. This is a true protocol.
    2. BaseAppBackend: Extends Core with most UI controls, containers, and non-interactive views. This is the protocol required by the App.Backend associated type.
    3. FullAppBackend: The most comprehensive composition. It includes everything in BaseAppBackend plus advanced features like URL handling, file dialogs, alerts, sheets, web views, tables, gestures, and windowing functionality.

    When building or extending a backend, you should aim for BaseAppBackend as the baseline, adding specific feature protocols from BackendFeatures as needed.

  3. Understand layout behavior for Stacks (VStack and HStack)

    main

    The SwiftCrossUI layout system adopts certain approximations to match SwiftUI's performance characteristics. When working with VStack or HStack, be aware of the following behaviors:

    • Minimum Height/Width: The minimum size of a stack is the sum of the minimum sizes of its children. This can cause a stack to overflow its frame if proposed its minimum size, especially when not inside a decoupling container like a ScrollView.
    • Concrete Dimensions: If a VStack is given a concrete height but an unspecified width, it may overflow its reported bounds because the final layout pass is delayed until the commit step.
    • Frame Clamping: When a minHeight frame is proposed an unspecified height, the child is first laid out with an unspecified height, then the frame clamps it. During the commit step, the child is laid out again with the clamped height. This can cause the unconstrained axis of a frame to not perfectly hug its content, even if it appears it should.
  4. How Dynamic Properties (State/Environment) are updated

    main

    Properties conforming to DynamicProperty (like @State or @Environment) are updated when view or app bodies are recomputed using two methods managed by DynamicPropertyUpdater:

    1. Primary Method (DynamicKeyPath): Uses DynamicKeyPath to construct a runtime key path by calculating the property's offset within the type using withUnsafeBytes. This is highly performant.
    2. Fallback Method (Mirror): If the primary method fails (e.g., due to bit-level collisions between properties), the system falls back to using Mirror to query and update properties. This method is significantly slower (up to 1500x) and is used only as a safety measure.
  5. Understand SwiftCrossUI navigation paradigms

    main

    SwiftCrossUI provides two primary navigation models for structuring your application's user interface:

    1. Hierarchical Navigation: Uses NavigationSplitView to create multi-column layouts (e.g., sidebar, content, and detail views), common in iPadOS or macOS-style applications.
    2. Stack-based Navigation: Uses NavigationStack to manage a stack of views that are pushed and popped, typical for mobile-style drill-down interfaces.
  6. How SwiftCrossUI apps start and initialize

    main

    The entry point for a SwiftCrossUI application is the implementation of the App protocol, specifically the main() function. When main() is called, it defers to _App.run(), which manages the backend lifecycle and application setup.

    The initialization sequence includes:

    1. Starting the backend's main loop.
    2. Computing the root Environment.
    3. Instantiating Environment properties on the app struct via updateDynamicProperties(of:previousValue:environment:).
    4. Observing State properties using Mirror and observeAsUIUpdater(backend:action:) (which includes update debouncing).
    5. Creating the root scene graph node.
    6. Listening for system-level environment changes (like theme changes).
    7. Updating the root scene graph node.