Skip to content

Commit 4f2b042

Browse files
committed
Add AsyncObservableReadOnly
If you want to expose an AsyncObservable as a read only property, you can use the AsyncObservableReadOnly protocol externally. class SomeClass { // .update is availble on the private property private let _someProperty = AsyncObservable(whatever) // but not on the public property, unless someone casts, but this should be enought of a deterrent var someProperty: AsyncObservableReadOnly<String> { _someProperty } }
1 parent fdf830a commit 4f2b042

File tree

3 files changed

+42
-1
lines changed

3 files changed

+42
-1
lines changed

README.md

+13
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,19 @@ let values = AsyncObservable([1, 2, 3])
121121
values.mutate { $0.append(4) }
122122
```
123123

124+
## Read Only
125+
126+
If you want to expose an AsyncObservable as a read only property, you can use the `AsyncObservableReadOnly` protocol externally.
127+
128+
```swift
129+
class SomeClass {
130+
// .update is availble on the private property
131+
private let _someProperty = AsyncObservable("whatever")
132+
// but not on the public property, unless someone casts, but this should be enought of a deterrent
133+
var someProperty: AsyncObservableReadOnly<String> { _someProperty }
134+
}
135+
```
136+
124137
## Buffering Policy
125138

126139
The buffering policy defaults to `.unbounded`, but you can change it on init.

Sources/AsyncObservable/AsyncObservable.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ import Observation
4747
/// }
4848
/// ```
4949
@available(iOS 17.0, macOS 14.0, tvOS 17.0, watchOS 10.0, *)
50-
open class AsyncObservable<T: Sendable>: @unchecked Sendable {
50+
open class AsyncObservable<T: Sendable>: AsyncObservableReadOnly, @unchecked Sendable {
5151
/// An Observable class that wraps the managed value for SwiftUI/UIKit integration.
5252
/// This class is bound to the MainActor to ensure all UI updates happen on the main thread.
5353
@Observable
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import Foundation
2+
import Dispatch
3+
4+
/// A protocol representing the read-only interface of an `AsyncObservable`.
5+
/// This allows for providing read-only access to an observable state without
6+
/// exposing methods that can modify the state.
7+
@available(iOS 17.0, macOS 14.0, tvOS 17.0, watchOS 10.0, *)
8+
public protocol AsyncObservableReadOnly<T>: Sendable {
9+
/// The type of value being observed.
10+
associatedtype T: Sendable
11+
12+
/// The observable state object for SwiftUI/UIKit integration.
13+
/// This property is accessed on the MainActor to ensure thread-safe UI updates.
14+
@MainActor
15+
var observable: AsyncObservable<T>.State { get }
16+
17+
/// The current value accessible from the MainActor.
18+
/// This is a convenience property that provides direct access to the observable value.
19+
@MainActor
20+
var valueObservable: T { get }
21+
22+
/// An async stream of values that can be used with Swift concurrency.
23+
/// This property provides a convenient way to access the value stream.
24+
var valueStream: StreamOf<T> { get }
25+
26+
/// The current value managed by this instance.
27+
var value: T { get }
28+
}

0 commit comments

Comments
 (0)