簡體   English   中英

如何在 SwiftUI 的視圖之外制作 State 包裝器?

[英]How can I make a State wrapper outside of View in SwiftUI?

我知道 State 包裝器是為 View 設計的,它們是為這個目標而設計的,但如果可能的話,我想嘗試構建和測試一些代碼,我的目標只是為了學習目的,

我的代碼有兩個大問題!

  1. Xcode 無法找到T

  2. 如何初始化我的 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM