Created
October 22, 2022 10:21
-
-
Save alexdremov/a4ffdddb714480bc31ad4f436ff34183 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class LogInState: ObservableObject { | |
@Published var isLoggedIn: Bool | |
init(isLoggedIn: Bool) { | |
self.isLoggedIn = isLoggedIn | |
} | |
func loggedOut() { | |
isLoggedIn = false | |
} | |
func loggedIn() { | |
isLoggedIn = true | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct MyView: View { | |
@ObservedObject var logInState: LogInState | |
var body: some View { | |
Text(logInState.isLoggedIn ? "Yes" : "No") | |
} | |
} | |
... | |
let logInState = LogInState(isLoggedIn: true) | |
HomePageModule(logInState: logInState) | |
... | |
SettingsModule(logInState: logInState) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct ReadOnlyModule: View { | |
@ObservedObject | |
@ObservableValue | |
var logInState: Bool | |
init(logInState: ObservableValue<Bool>) { | |
self._logInState = .init(wrappedValue: logInState) | |
} | |
var body: some View { | |
Text(logInState ? "Yes" : "No") | |
} | |
} | |
struct ModifyModule: View { | |
@ObservableProperty | |
var logInState: Bool | |
init(logInState: ObservableProperty<Bool>) { | |
self._logInState = logInState | |
} | |
var body: some View { | |
Button("toggle") { | |
logInState = !logInState | |
} | |
} | |
} | |
struct MyView: View { | |
@ObservableProperty | |
var logInState: Bool | |
init(logInState: ObservableProperty<Bool>) { | |
self._logInState = logInState | |
} | |
var body: some View { | |
VStack { | |
// projected read-only value (ObservableValue) | |
ReadOnlyModule(logInState: $logInState) | |
// ObservableProperty reference | |
ModifyModule(logInState: _logInState) | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct MyView: View { | |
@ObservedObject | |
@ObservableProperty | |
var logInState: Bool | |
init(logInState: ObservableProperty<Bool>) { | |
self._logInState = .init(initialValue: logInState) | |
} | |
var body: some View { | |
VStack { | |
Text(logInState ? "Yes" : "No") | |
Button("toggle") { | |
logInState = !logInState | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@dynamicMemberLookup | |
@propertyWrapper | |
public class ObservableProperty<Output>: ObservableObject { | |
@Published private var storedValue: Output | |
public var wrappedValue: Output { | |
get { | |
storedValue | |
} | |
set { | |
storedValue = newValue | |
} | |
} | |
public init(wrappedValue initialValue: Output) { | |
self.storedValue = initialValue | |
} | |
public subscript<Result>(dynamicMember keyPath: WritableKeyPath<Output, Result>) -> Result { | |
get { | |
storedValue[keyPath: keyPath] | |
} | |
set { | |
storedValue[keyPath: keyPath] = newValue | |
} | |
} | |
public subscript<Result>(dynamicMember keyPath: KeyPath<Output, Result>) -> Result { | |
storedValue[keyPath: keyPath] | |
} | |
public var publisher: AnyPublisher<Output, Never> { | |
$storedValue.eraseToAnyPublisher() | |
} | |
public var projectedValue: ObservableValue<Output> { | |
ObservableValue<Output>( | |
initialValue: storedValue, | |
publisher: publisher | |
) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ObservableProperty<Output>: ObservableObject { | |
... | |
public var publisher: AnyPublisher<Output, Never> { | |
$storedValue.eraseToAnyPublisher() | |
} | |
public var projectedValue: ObservableValue<Output> { | |
ObservableValue<Output>( | |
initialValue: storedValue, | |
publisher: publisher | |
) | |
} | |
... | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import Combine | |
@dynamicMemberLookup | |
@propertyWrapper | |
public class ObservableProperty<Output>: ObservableObject { | |
@Published private var storedValue: Output | |
public var wrappedValue: Output { | |
get { | |
storedValue | |
} | |
set { | |
storedValue = newValue | |
} | |
} | |
public init(wrappedValue initialValue: Output) { | |
self.storedValue = initialValue | |
} | |
public subscript<Result>(dynamicMember keyPath: WritableKeyPath<Output, Result>) -> Result { | |
get { | |
storedValue[keyPath: keyPath] | |
} | |
set { | |
storedValue[keyPath: keyPath] = newValue | |
} | |
} | |
public subscript<Result>(dynamicMember keyPath: KeyPath<Output, Result>) -> Result { | |
storedValue[keyPath: keyPath] | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@dynamicMemberLookup | |
@propertyWrapper | |
public class ObservableValue<Output>: ObservableObject { | |
@Published private var storedValue: Output | |
private var cancellable: AnyCancellable? | |
public var wrappedValue: Output { | |
storedValue | |
} | |
public init(wrappedValue initialValue: Output) { | |
fatalError("ObservableValue cannot be initialized with value. Use constant()") | |
} | |
init<Pub: Publisher<Output, Never>>(initialValue: Output, publisher: Pub) { | |
storedValue = initialValue | |
cancellable = publisher.sink { newValue in | |
self.storedValue = newValue | |
} | |
} | |
public subscript<Result>(dynamicMember keyPath: WritableKeyPath<Output, Result>) -> Result { | |
get { | |
storedValue[keyPath: keyPath] | |
} | |
set { | |
storedValue[keyPath: keyPath] = newValue | |
} | |
} | |
public subscript<Result>(dynamicMember keyPath: KeyPath<Output, Result>) -> Result { | |
storedValue[keyPath: keyPath] | |
} | |
public static func constant(initialValue: Output) -> ObservableValue<Output> { | |
.init( | |
initialValue: initialValue, | |
publisher: Empty() | |
) | |
} | |
public var publisher: Published<Output>.Publisher { | |
$storedValue | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment