[英]How can I make a State wrapper outside of View in SwiftUI?
I know that State wrappers are for View and they designed for this goal, but I wanted to try build and test some code if it is possible, my goal is just for learning purpose,我知道 State 包装器是为 View 设计的,它们是为这个目标而设计的,但如果可能的话,我想尝试构建和测试一些代码,我的目标只是为了学习目的,
I have 2 big issues with my code!我的代码有两个大问题!
Xcode is unable to find T . Xcode 无法找到T 。
How can I initialize my state?如何初始化我的 state?
import SwiftUI
var state: State<T> where T: StringProtocol = State(get: { state }, set: { newValue in state = newValue })
struct ContentView: View {
var body: some View {
Text(state)
}
}
Update: I could do samething for Binding here, Now I want do it for State as well with up code更新:我可以在这里为 Binding 做同样的事情,现在我想为 State 以及 up 代码做同样的事情
import SwiftUI
var state2: String = String() { didSet { print(state2) } }
var binding: Binding = Binding.init(get: { state2 }, set: { newValue in state2 = newValue })
struct ContentView: View {
var body: some View {
TextField("Enter your text", text: binding)
}
}
If I could find the answer of my issue then, i can define my State and Binding both outside of View, 50% of this work done and it need another 50% for State Wrapper.如果我能找到我的问题的答案,我可以定义我的 State 并在视图之外进行绑定,完成了 50% 的工作,State Wrapper 还需要另外 50%。
New Update:新更新:
import SwiftUI
var state: State<String> = State.init(initialValue: "Hello") { didSet { print(state.wrappedValue) } }
var binding: Binding = Binding.init(get: { state.wrappedValue }, set: { newValue in state = State(wrappedValue: newValue) })
struct ContentView: View {
var body: some View {
Text(state) // <<: Here is the issue!
TextField("Enter your text", text: binding)
}
}
Even if you create a State wrapper outside a view, how will the view know when to refresh its body?即使您在视图之外创建了 State 包装器,视图如何知道何时刷新其主体?
Without a way to notify the view, your code will do the same as:如果没有通知视图的方法,您的代码将执行以下操作:
struct ContentView: View {
var body: some View {
Text("Hello")
}
}
What you can do next depends on what you want to achieve.接下来你能做什么取决于你想要达到的目标。
If all you need is a way to replicate the State behaviour outside the view, I recommend you take a closer look at the Combine framework.如果您只需要一种在视图外复制 State 行为的方法,我建议您仔细查看 Combine 框架。
An interesting example is CurrentValueSubject
:一个有趣的例子是CurrentValueSubject
:
var state = CurrentValueSubject<String, Never>("state1")
It stores the current value and also acts as a Publisher.它存储当前值并充当发布者。
What will happen if we use it in a view that doesn't observe anything?如果我们在不观察任何东西的视图中使用它会发生什么?
struct ContentView: View {
var body: some View {
Text(state.value)
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
state.value = "state2"
}
}
}
}
The answer is: nothing.答案是:什么都没有。 The view is drawn once and, even if the state
changes, the view won't be re-drawn.视图只绘制一次,即使state
发生变化,也不会重新绘制视图。
You need a way to notify the view about the changes.您需要一种方法来通知视图有关更改。 In theory you could do something like:从理论上讲,您可以执行以下操作:
var state = CurrentValueSubject<String, Never>("state1")
struct ContentView: View {
@State var internalState = ""
var body: some View {
Text(internalState)
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
state.value = "state2"
}
}
.onReceive(state) {
internalState = $0
}
}
}
But this is neither elegant nor clean.但这既不优雅也不干净。 In these cases we should probably use @State
:在这些情况下,我们可能应该使用@State
:
struct ContentView: View {
@State var state = "state1"
var body: some View {
Text(state)
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
state = "state2"
}
}
}
}
To sum up, if you need a view to be refreshed, just use the native SwiftUI property wrappers (like @State
).总而言之,如果您需要刷新视图,只需使用本机 SwiftUI 属性包装器(如@State
)。 And if you need to declare state values outside the view, use ObservableObject
+ @Published
.如果您需要在视图外声明 state 值,请使用ObservableObject
+ @Published
。
Otherwise there is a huge Combine framework which does exactly what you want.否则,有一个巨大的组合框架可以完全满足您的需求。 I recommend you take a look at these links:我建议你看看这些链接:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.