[英]How can I make a State wrapper outside of View in SwiftUI?
我知道 State 包裝器是為 View 設計的,它們是為這個目標而設計的,但如果可能的話,我想嘗試構建和測試一些代碼,我的目標只是為了學習目的,
我的代碼有兩個大問題!
Xcode 無法找到T 。
如何初始化我的 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)
}
}
更新:我可以在這里為 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)
}
}
如果我能找到我的問題的答案,我可以定義我的 State 並在視圖之外進行綁定,完成了 50% 的工作,State Wrapper 還需要另外 50%。
新更新:
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)
}
}
即使您在視圖之外創建了 State 包裝器,視圖如何知道何時刷新其主體?
如果沒有通知視圖的方法,您的代碼將執行以下操作:
struct ContentView: View {
var body: some View {
Text("Hello")
}
}
接下來你能做什么取決於你想要達到的目標。
如果您只需要一種在視圖外復制 State 行為的方法,我建議您仔細查看 Combine 框架。
一個有趣的例子是CurrentValueSubject
:
var state = CurrentValueSubject<String, Never>("state1")
它存儲當前值並充當發布者。
如果我們在不觀察任何東西的視圖中使用它會發生什么?
struct ContentView: View {
var body: some View {
Text(state.value)
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
state.value = "state2"
}
}
}
}
答案是:什么都沒有。 視圖只繪制一次,即使state
發生變化,也不會重新繪制視圖。
您需要一種方法來通知視圖有關更改。 從理論上講,您可以執行以下操作:
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
}
}
}
但這既不優雅也不干凈。 在這些情況下,我們可能應該使用@State
:
struct ContentView: View {
@State var state = "state1"
var body: some View {
Text(state)
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
state = "state2"
}
}
}
}
總而言之,如果您需要刷新視圖,只需使用本機 SwiftUI 屬性包裝器(如@State
)。 如果您需要在視圖外聲明 state 值,請使用ObservableObject
+ @Published
。
否則,有一個巨大的組合框架可以完全滿足您的需求。 我建議你看看這些鏈接:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.