Skip to content

Commit

Permalink
Improve Constant to include var and let variables (#72)
Browse files Browse the repository at this point in the history
  • Loading branch information
0xLeif authored Jan 18, 2024
1 parent 4dcf671 commit 9ac0ed4
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 6 deletions.
37 changes: 34 additions & 3 deletions Sources/AppState/PropertyWrappers/Constant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ import Combine
import SwiftUI

/// A property wrapper that provides access to a specific part of the AppState's state.
@propertyWrapper public struct Constant<SlicedState: MutableApplicationState, Value, SliceValue> where SlicedState.Value == Value {
@propertyWrapper public struct Constant<SlicedState: MutableApplicationState, Value, SliceValue, SliceKeyPath: KeyPath<Value, SliceValue>> where SlicedState.Value == Value {
/// Holds the singleton instance of `Application`.
@ObservedObject private var app: Application = Application.shared

/// Path for accessing `State` from Application.
private let stateKeyPath: KeyPath<Application, SlicedState>

/// Path for accessing `SliceValue` from `Value`.
private let valueKeyPath: KeyPath<Value, SliceValue>
private let valueKeyPath: SliceKeyPath

private let fileID: StaticString
private let function: StaticString
Expand Down Expand Up @@ -44,7 +44,38 @@ import SwiftUI
_ function: StaticString = #function,
_ line: Int = #line,
_ column: Int = #column
) {
) where SliceKeyPath == KeyPath<Value, SliceValue> {
self.stateKeyPath = stateKeyPath
self.valueKeyPath = valueKeyPath
self.fileID = fileID
self.function = function
self.line = line
self.column = column

let stateKeyPathString = String(describing: stateKeyPath)
let valueTypeCharacterCount = String(describing: Value.self).count
var valueKeyPathString = String(describing: valueKeyPath)

valueKeyPathString.removeFirst(valueTypeCharacterCount + 1)

self.sliceKeyPath = "\(stateKeyPathString)\(valueKeyPathString)"
}

/**
Initializes a Slice with the provided parameters. This constructor is used to create a Slice that provides access and modification to a specific part of an AppState's state. It provides granular control over the AppState.

- Parameters:
- stateKeyPath: A KeyPath that points to the state in AppState that should be sliced.
- valueKeyPath: A WritableKeyPath that points to the specific part of the state that should be accessed.
*/
public init(
_ stateKeyPath: KeyPath<Application, SlicedState>,
_ valueKeyPath: WritableKeyPath<Value, SliceValue>,
_ fileID: StaticString = #fileID,
_ function: StaticString = #function,
_ line: Int = #line,
_ column: Int = #column
) where SliceKeyPath == WritableKeyPath<Value, SliceValue> {
self.stateKeyPath = stateKeyPath
self.valueKeyPath = valueKeyPath
self.fileID = fileID
Expand Down
9 changes: 6 additions & 3 deletions Tests/AppStateTests/SliceTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ fileprivate struct ExampleValue {
var username: String?
var isLoading: Bool
let value: String
var mutableValue: String
}

fileprivate extension Application {
Expand All @@ -14,7 +15,8 @@ fileprivate extension Application {
initial: ExampleValue(
username: "Leif",
isLoading: false,
value: "value"
value: "value",
mutableValue: ""
)
)
}
Expand All @@ -32,13 +34,14 @@ fileprivate class ExampleViewModel: ObservableObject {
fileprivate struct ExampleView: View {
@Slice(\.exampleValue, \.username) var username
@Slice(\.exampleValue, \.isLoading) var isLoading

@Constant(\.exampleValue, \.mutableValue) var constantMutableValue

var body: some View { fatalError() }

func testPropertyWrappers() {
username = "Hello, ExampleView"
_ = Toggle(isOn: $isLoading) {
Text("Is Loading")
Text(constantMutableValue)
}
}
}
Expand Down

0 comments on commit 9ac0ed4

Please sign in to comment.