每次渲染正文时都会调用 SwiftUI Picker onReceive()

Posted

技术标签:

【中文标题】每次渲染正文时都会调用 SwiftUI Picker onReceive()【英文标题】:SwiftUI Picker onReceive() called every time the body is rendered 【发布时间】:2020-07-10 18:02:37 【问题描述】:

我正在使用Picker 来显示分段控件,并希望知道选择器值何时更改,以便我可以执行非 UI 操作。使用建议的onReceive() 修饰符(建议here)不起作用,因为每次渲染主体时都会调用它。

这是我的代码:

struct PickerView: View 

    @State private var weather = 0
    @State private var showMessage = false

    var body: some View 

        VStack(spacing: 24) 
            Picker(selection: $weather, label: Text("Weather")) 
                Image(systemName: "sun.max.fill").tag(0)
                Image(systemName: "cloud.sun.rain.fill").tag(1)
            
            .pickerStyle(SegmentedPickerStyle())
            .frame(width: 120, height: 48)
            .onReceive([weather].publisher.first())  connectionType in
                print("connection type is: \(connectionType)")
            

            Button(action:  self.showMessage.toggle() ) 
                Text("Press Me")
            

            if showMessage 
                Text("Hello World")
            
        
    

onReceive() 块将在主体被渲染的任何时候被调用,包括第一次和任何时候按钮(用于切换显示消息)被按下。

任何想法为什么会发生这种情况以及我如何只能在选择器值更改时做出反应?

【问题讨论】:

代理绑定,Asperi 发布的答案是解决这个问题的方法;) 【参考方案1】:

这是可能的解决方案,而不是 .onReceive

Picker(selection: Binding(           // << proxy binding
                get:  self.weather ,
                set:  self.weather = $0
                    print("connection type is: \($0)")  // side-effect
                )
    , label: Text("Weather")) 
    Image(systemName: "sun.max.fill").tag(0)
    Image(systemName: "cloud.sun.rain.fill").tag(1)

【讨论】:

以上是关于每次渲染正文时都会调用 SwiftUI Picker onReceive()的主要内容,如果未能解决你的问题,请参考以下文章

在 Vuejs 中使用 beforemount 进行数据渲染,每次打开该组件/页面时都会不断增加渲染的数据列表

从不同的文件 SwiftUI 调用核心数据对象

为啥每次选择另一个 TextField 时都会调用 KeyboardWillShowNotification?

为啥ajax调用在每次调用时都会输入成功和错误块?

每次调用 Func 时都会重写 UIView

每次设置状态时都会调用 Flutter 函数