Any future directions for supporting Observable Structs?

Hi! Last year we removed the ability to mark structs as Observable.[1] I didn't see any mention of supporting structs in the 0395 proposal.[2] Can anyone tell me where I can follow along to learn if there were any new plans to supporting Observable on struct value types? Or do we plan to keep this only supported on classes for the near future? Thanks!


  1. Make the `@Observable` macro class only by natecook1000 · Pull Request #67033 · apple/swift · GitHub ↩︎

  2. swift-evolution/proposals/0395-observability.md at main · apple/swift-evolution · GitHub ↩︎

3 Likes

@nnnnnnnn did you have any more documentation or announcements we can follow along for more information about that? Thanks!

Apple doesn't often comment on future plans, including Swift's. So unless there's work happening in public you're unlikely to hear anything about concrete plans for language features. FWIW, PointFree has enabled observable structs in the Swift Composable Architecture through the use of a macro which adds a unique id value, allowing difference tracking over time. That, in combination with their new swift-perception library which backports Observable to iOS 13, allowed TCA to switch to a fully observable but struct based state system.

3 Likes

@Jon_Shier thanks!

This was brought up during the proposal period and there was quite a bit back-and-forth starting here and ending with this, if you want to catch up

3 Likes

@mbrandonw ahh… interesting! thanks!

Perhaps not with ObservableObject or Observable, but it is possible to observe structs by other means. Example:

import SwiftUI

struct S { var value = 0 }

func foo(_ x: Binding<S>) {
    Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
        x.wrappedValue.value += 1
    }
}

struct ContentView: View {
    @State private var x = S()
    var body: some View {
        Text(String(x.value))
            .onAppear { foo($x) }
    }
}

@main struct SSSApp: App {
    var body: some Scene {
        WindowGroup { ContentView() }
    }
}