From 9ac0ed446be95941550d02e0cb2e8b7a5fe3abf6 Mon Sep 17 00:00:00 2001 From: Zach Date: Wed, 17 Jan 2024 19:28:07 -0700 Subject: [PATCH] Improve Constant to include var and let variables (#72) --- .../AppState/PropertyWrappers/Constant.swift | 37 +++++++++++++++++-- Tests/AppStateTests/SliceTests.swift | 9 +++-- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/Sources/AppState/PropertyWrappers/Constant.swift b/Sources/AppState/PropertyWrappers/Constant.swift index ec2bf54..c667fc2 100644 --- a/Sources/AppState/PropertyWrappers/Constant.swift +++ b/Sources/AppState/PropertyWrappers/Constant.swift @@ -2,7 +2,7 @@ import Combine import SwiftUI /// A property wrapper that provides access to a specific part of the AppState's state. -@propertyWrapper public struct Constant where SlicedState.Value == Value { +@propertyWrapper public struct Constant> where SlicedState.Value == Value { /// Holds the singleton instance of `Application`. @ObservedObject private var app: Application = Application.shared @@ -10,7 +10,7 @@ import SwiftUI private let stateKeyPath: KeyPath /// Path for accessing `SliceValue` from `Value`. - private let valueKeyPath: KeyPath + private let valueKeyPath: SliceKeyPath private let fileID: StaticString private let function: StaticString @@ -44,7 +44,38 @@ import SwiftUI _ function: StaticString = #function, _ line: Int = #line, _ column: Int = #column - ) { + ) where SliceKeyPath == KeyPath { + 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, + _ valueKeyPath: WritableKeyPath, + _ fileID: StaticString = #fileID, + _ function: StaticString = #function, + _ line: Int = #line, + _ column: Int = #column + ) where SliceKeyPath == WritableKeyPath { self.stateKeyPath = stateKeyPath self.valueKeyPath = valueKeyPath self.fileID = fileID diff --git a/Tests/AppStateTests/SliceTests.swift b/Tests/AppStateTests/SliceTests.swift index be86da0..8233bf0 100644 --- a/Tests/AppStateTests/SliceTests.swift +++ b/Tests/AppStateTests/SliceTests.swift @@ -6,6 +6,7 @@ fileprivate struct ExampleValue { var username: String? var isLoading: Bool let value: String + var mutableValue: String } fileprivate extension Application { @@ -14,7 +15,8 @@ fileprivate extension Application { initial: ExampleValue( username: "Leif", isLoading: false, - value: "value" + value: "value", + mutableValue: "" ) ) } @@ -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) } } }