【问题标题】:How could be change children @State property value from parent view in SwiftUI?如何在 SwiftUI 中从父视图更改子 @State 属性值?
【发布时间】:2021-08-03 08:36:12
【问题描述】:

鉴于此代码:

import SwiftUI

struct ContentView: View {
    @State private var someView = DefaultView()
    var body: some View {
        VStack { someView }
            //.onAppear { someView.change() } //1. Color not changing from here, isDisplay remains false
    }
}

struct DefaultView: View {
    @State private var isDisplay = false

    func change() {
        isDisplay = true
        print("isDisplay = \(self.isDisplay)")
    }

    var body: some View {
        Text("Hello!")
            .foregroundColor(isDisplay ? .red : .blue)
            //.onAppear { change() } //2. Color and isDisplay property is changing from here well
    }
}

我想从父视图(ContentView 1.)调用更改函数。运行是因为打印在调试区域上可见,但没有任何更改,isDisplay 属性不会从 false 更改为 true。 为什么会这样?如何更改父类的@state 属性?

编辑: 它可以工作:

struct DefaultView: View {
    public var isDisplay: Bool

    init() {
        isDisplay = false
    }

    mutating func change() {
        isDisplay = true
        print("isDisplay = \(self.isDisplay)")
    }

    var body: some View {
        Text("Hello!")
            .foregroundColor(isDisplay ? .red : .blue)
    }
}

【问题讨论】:

  • 试一试:在主队列中添加这一行。 someView.change()
  • 谢谢,但它已经在主线程上。 (:

标签: swiftui


【解决方案1】:

我会使用@Binding 从父视图更改DefaultView 中的属性值。这是一个简短的例子。

struct ContentView: View {
    @State private var changeColor = false

    var body: some View {
        VStack {
            Button {
                changeColor.toggle()
            } label: {
                Text("Toggle Button")
                    .padding()
                    .foregroundColor(.red)
            }

            DefaultView(isDisplay: $changeColor)
        }
    }

}

struct DefaultView: View {
    @Binding var isDisplay: Bool

    var body: some View {
        Text("Hello")
            .foregroundColor(isDisplay ? .red : .blue)
    }
}

【讨论】:

  • Binding 没有用例,DefaultView 不会更新状态!只需使用 let!
  • 谢谢,但 swiftPunk 是对的!如果孩子不需要更新值,就不需要Binding。当孩子想对父母隐藏自己时,绑定可能很有用。
【解决方案2】:

你展示你的代码的方式不是 SwiftUI 的工作方式,你是在 UIKit 中思考和编码 SwiftUI?

一旦你触发了一个视图,就不能再使用嵌入的函数或任何东西了! SwiftUI-View 更像是一把枪,渲染完成后你不能改变它的方向或其他属性!另一方面,UIKit-View 更像 Rocket,发射后你可以控制它,你可以改变目的地和更多其他的东西。因此它们之间存在尊重,使您的构建尽可能轻。因为您要大量使用,而 SwiftUI 应该尽可能轻松地处理它们。
这里是正确的方式:

struct ContentView: View {
    
    @State private var isDisplay: Bool = Bool()
    
    var body: some View {

        DefaultView(isDisplay: isDisplay)
        
        Button("update") { isDisplay.toggle() }.padding()
        
    }
}



struct DefaultView: View {
    
    let isDisplay: Bool

    var body: some View {
        
        Text("Hello!")
            .foregroundColor(isDisplay ? .red : .blue)
        
    }
    
}

【讨论】:

  • 是的,你说得对,这不是 SwiftUI 方式,我只是在尝试一些东西。反正我已经找到了方法,我想展示一下,只是我不知道如何在此处粘贴代码。
  • 我已经更新了我原来的帖子。很好地使用“变异函数”。 Ofc 一点也不优雅。
  • 我过去曾尝试过很多此类代码,当您将 View 类型用于 State 属性时,它会使项目比应有的更加繁重和复杂。
  • 你说得差不多了,因为我想将 UIKit 逻辑引入 SwiftUI 项目。但是,尽管我尝试了很多,但似乎我必须重建。 ^^" 谢谢!
  • 不客气,我最终重建了我的一些项目,但你也可以考虑在 UIKit 中使用 SwiftUI-View,这也是一种方式。
猜你喜欢
  • 1970-01-01
  • 2021-10-19
  • 2021-01-31
  • 2017-09-07
  • 2020-11-22
  • 1970-01-01
  • 1970-01-01
  • 2020-05-22
  • 2023-04-10
相关资源
最近更新 更多