Replies: 25 comments 113 replies
-
Switch to the beta branch. Everything is fine with compilation and tests, although I should mention that there are only a few of them at the moment, as the project is new and under active development. If I understand correctly, @.Shared is only applicable within reducers, right? But what if we need to modify the shared state within some dependency? I believe many of us, if not all, deal with the following scenario: We need to log out by clearing/refreshing access tokens if our ApiClient dependency encounters a 401 error for any request. Currently, I'm using the approach mentioned in the last episode, with a get-set-stream where my authReducer is listening to the stream from another dependency named SharedState, where these apiTokens reside in memory. When my app starts, the authReducer reads values from keychain and sets persisted token to SharedState dependency, which is using by apiClient for network requests. When the SharedState dependency's stream sends nil , authReducer will clear the keychain/sharedState and send action to the parent for logout on UI level) |
Beta Was this translation helpful? Give feedback.
-
I would have use if I understand this is probably the minority use-case and you may have considered reasons for providing the defaults you do. Just putting it out there; you could save me some copy-paste implementation. |
Beta Was this translation helpful? Give feedback.
-
I have hit an unexpected TestStore behaviour when testing feature composition which uses both shared state and delegation actions pattern. Here is an example project: https://github.com/Malauch/tca-shared-state-delegate-action-test-issue. It's very artificial stripped down example but illustrates the issue. The problem is that if a child feature sends delegate action which when is received by parent feature it causes mutation of shared state (in parent feature reducer), then test store shows state mutation on sending delegate action instead of receiving it. When commenting out shared state property wrapper attribute and use just normal property it works as expected. |
Beta Was this translation helpful? Give feedback.
-
I tried to convert one of my shared state dependency client into this new shared state machinery. That dependency client was also saving data on disk for purpose of persistence and sharing data with widgets. Therefore I used I have some other project when helper and main app runs as two separate processes and exchange data via saving and monitoring changes to filesystem. It's implemented using similar mechanism as fileStorage persistence strategy. I didn't try it yet but it should be possible to easily replace this communication dependency client with shared state machinery. However that 5 s. delay would be too long. Is this 5s really minimum reasonable value? Do you have any plan to make it configurable? |
Beta Was this translation helpful? Give feedback.
-
Excellent! "persistence" is indeed a crucial component missing from the TCA framework 🙌🏻 I have tried to migrate one of my projects to this new tool and although it was not as straight as I expected, it (kind of) worked! Nice! However, it seems more like a What are your thoughts on this? Oh and:
|
Beta Was this translation helpful? Give feedback.
-
Yep, no problems here. Updating and building worked fine
Tests passed, no behavioural difference noticed. To note, my test suite is small.
Converted a feature today and it went smoothly. This feature was a multistep form using a coordinator that manages a navigation stack. Previously I was doing at least 2 nasty things to pass data around: A few things I had trouble with while converting.
|
Beta Was this translation helpful? Give feedback.
-
Hello. 👋 I started updating one of my projects and ran into a strange issue. I also have a question. First the question. What's the recommended way to use Now, the strange issue. Create a brand new app, add TCA with the import ComposableArchitecture
import Foundation
@Reducer
public struct Foo {
public struct State: Equatable {
@Shared(.appStorage("foo")) public internal(set) var foo: Int? = nil
public init() {}
}
}
@Reducer
public struct AppDelegate {
public struct State: Equatable {
@Shared(.appStorage("dateOfFirstLaunch")) public internal(set) var dateOfFirstLaunch: Date? = nil
public init() {}
}
} When you try to build it, you should get the errors Type 'AppDelegate.State' does not conform to protocol 'Equatable' and No exact matches in call to static method 'appStorage' but only for the Any ideas? Many thanks in advance. |
Beta Was this translation helpful? Give feedback.
-
Hello, on my SwiftUI macOS app, I tried |
Beta Was this translation helpful? Give feedback.
-
Can somebody provide an example of how to observe changes of a shared state property in a reducer? The reducer should react to such changes for example by sending an action. Currently I do create a long running effect using the shared values Publisher:
But that does not work completely as expected. Although I use Another problem is that I need to trigger an action whenever one of two shared values changes. Currently I need to create two effects (like the one above) and merge them, where both effects trigger the same action:
This is a lot of boilerplate code... |
Beta Was this translation helpful? Give feedback.
-
Thanks for the work, guys -- I'm excited about this new addition to the framework. How do you recommend setting up a migration strategy when using file storage persistence? I could write to a separate file with version info and use that to direct the loading of the data, but there doesn't appear to be a way to intervene in the load process as the framework stands. I suppose I could write my own |
Beta Was this translation helpful? Give feedback.
-
Is specifying a custom UserDefaults suite supported with appStorage? |
Beta Was this translation helpful? Give feedback.
-
Has there been any discussion on how utilizing shared state would work when it comes to destination enums, where only certain cases would utilize shared state functionality? For example, in my @Reducer
public struct Home {
@Reducer(state: .equatable, action: .equatable)
public enum Destination {
case mediaLibrary(Shared<MediaLibrary>)
case settings(Settings)
}
} However, this certainly doesn't work because the macro expects a reducer and not a reducer wrapped in case .view(.mediaLibraryButtonTapped):
return .run { @MainActor send in
let state: Shared<MediaLibrary.State> = .init(
wrappedValue: .init(),
.inMemory("mediaLibrary")
)
send(.internal(.destinationResponse(.mediaLibrary(state.wrappedValue))))
}
) But that also doesn't work because that instance isn't saved anywhere. One may say to just slap on Are there any alternatives other than just having a reference to |
Beta Was this translation helpful? Give feedback.
-
Hi! So far using the branch was flawless and didn't break anything in my application. One thing I'm struggling with though are non-exhaustive tests. I get the I haven't found a way to use |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
I'm having some difficulty with overriding |
Beta Was this translation helpful? Give feedback.
-
The only snag I've come across so far is the naming of the PersistenceKey function...
With my Firebase RemoteConfig implementation I have an So in the closure I run the However... the ideal way of doing this is like...
But... The compiler doesn't like this as it thinks I'm trying to use the I can change this to something like...
But it would be nice to not have to do that. Would it be possible to rename the 😄 Thanks |
Beta Was this translation helpful? Give feedback.
-
I was wondering if I'm the only one who thinks it could be useful to have As a side note: could be also useful to explore the possibility to sync those UserDefaults values into iCloud, maybe with NSUbiquitousKeyValueStore. What do you think? Thanks! |
Beta Was this translation helpful? Give feedback.
-
Is there any way to scope/map a For example, I'm trying to do something like this... @Reducer
struct Child {
@ObservableState
struct State {
@Shared var customer: Customer
// other properties
}
}
@Reducer
struct Parent {
@ObservableState
struct State {
@Shared var customer: Customer?
var childState: Child.State?
}
var body: some ReducerOf<Self> {
BindingReducer()
Reduce { state, action in
switch action {
case .binding(\.customer):
// if customer is set to non-nil value for the first time, initialize childState
// if customer is set to nil, set childState to nil
}
}
}
In the above example, the child state is only valid if a customer is selected. The user needs to take action to select a customer which should then create the childState and their customer properties should stay in sync as long as a non-nil customer is selected on the parent. |
Beta Was this translation helpful? Give feedback.
-
I've been trying the beta using an icloud drive to save the data. It kind of works but isn't great when 2 copies are running at the same time. Most changes get seen on the other copy but I've had some weird things like only half the new text of an item is seen. Are there any plans to add functionality to deal with this kind of thing or is it something I could take care of with a custom persistence? |
Beta Was this translation helpful? Give feedback.
-
For a macOS app willTerminateNotification is definitely needed to not lose data when the application quits. |
Beta Was this translation helpful? Give feedback.
-
I'm creating some more custom When creating the Defined as...
But... the Because I think the The So, this would only ever It looks like there isn't ever a trigger that occurs when a Gonna try something else. But right now it's not running the |
Beta Was this translation helpful? Give feedback.
-
Hiey, I'm working with this shared-beta branch for a while and I'm thrilled how great it all works. What I noticed is that the publisher is only emitting changes that happen after the subscription. It would be great if this could behave like a CurrentValueSubject (or provide a way to define the behavior) and provide the current value upon subscription. Is there something I'm missing here? |
Beta Was this translation helpful? Give feedback.
-
I seem to have run into an issue with inMemory Shared publisher observation. I am observing the publisher in an onTask action such as:
However if the the feature this is in goes away (More on this in a minute) and I write to the shared property from somewhere else, the action is still being fired and I get the purple warning of doom. So my set up at root is such that I have a SignInView and a HomeView and root swaps these features based on authentication state that can change from a couple different places. So when authenticated we show HomeView when not we show SignInView. This is handled similar to this:
The problem arises when HomeView pushes a childview that has that task observation then authentication switches while it is presented, if I then mutate that inMemory property from root, I get the error. It appears that the publisher is holding onto the child. Is this a memory leak? I have a full demo I can paste here if anyone wants. I have also raised this on Slack where I pasted the full demo of this happening. This seems to be a very common pattern in setting up sign in and home view based on auth state, so am I just doing it wrong? |
Beta Was this translation helpful? Give feedback.
-
I started using the beta this last week to see how it goes with sharing settings in my app. I was looking at how things work with file storage persistence. It calls this init in ValueReference.swift: extension Shared {
public init(
wrappedValue value: Value,
_ persistenceKey: some PersistenceKey<Value>,
fileID: StaticString = #fileID,
line: UInt = #line
) { ... }
} which got me looking at all of them and I am wondering if all the wrappedValue portions should be changed to |
Beta Was this translation helpful? Give feedback.
-
I'm going to close this discussion now that the tools have been officially released. |
Beta Was this translation helpful? Give feedback.
-
Hello all, today we are beginning a very exciting beta for the Composable Architecture. It brings all new tools to the library for sharing state in your application and persisting data.
To try out the beta you can point your dependency on the Composable Architecture to the
shared-state-beta
branch. We have prepared a migration guide that can be followed to try updating some of your features, and there is a dedicated article with more information on the tools.We do not recommend depending on this beta branch for long term, active development of your application. It is likely to have many breaking changes in the coming weeks or months until its final release.
But we would appreciate if everyone could point their projects to the
shared-state-beta
branch and let us know a few things:@Shared
in a few features, and does it behave as you expect when running your application and tests?@Shared
cannot do that you would like it to do?Beta Was this translation helpful? Give feedback.
All reactions