Binding 对象更改其状态变量后,SwiftUI contentView 不会重新渲染

问题描述 投票:0回答:1

我试图让我的按钮“habitEggButton”在不同文件中使用@State和@Binding后消失,但我似乎无法让它工作。我对 Swift 还很陌生,所以我不太确定所有工作部分都能协同工作。

习惯:

import Foundation
import SwiftUI

struct Habit : Identifiable {
    let id = UUID()
    var habitName: String
    var isDisplayed: Bool
}

习惯蛋按钮:

import Foundation
import SwiftUI

struct HabitEggButton: View {
    @Binding var habit : Habit
    
    var body: some View {
        Button(action: {
            print(habit.habitName + " button tapped")
            if habit.isDisplayed {
                print("Yes")
            }
            else {
                print("No")
            }
        }) {
            Image("egg_uncracked")
                .resizable()
                .frame(width: 120, height: 120)
        }
        .supportsLongPress {
            habit.isDisplayed = false
            
            print(habit.habitName + " button held")
        }
    }
}

内容视图:

import SwiftUI
import UIKit
extension UIScrollView {  open override var clipsToBounds: Bool {   get { false }   set { }  } }

struct ContentView: View {
    @State private var fulfilled = 0
    @State private var numOfEggs = 3
    @State private var displayState = true
    @State private var displayHabit = " "
    
    @State var name = "Drink Water"
    @State var display = true
    
    @State var habit1IsDisplayed = true

    @State private var habits: [Habit] = [
            Habit(habitName: "Run", isDisplayed: true),
            Habit(habitName: "Fight", isDisplayed: true),
            Habit(habitName: "Jump", isDisplayed: true)
    ]
    
    var body: some View {        
        NavigationView {
            let chickenImageName = fulfilled == numOfEggs ? "chicken_in_egg" : "chicken_in_egg_sad"
            
            ZStack {
                Color(#colorLiteral(red: 0.9294117647, green: 0.9294117647, blue: 0.9137254902, alpha: 1)).ignoresSafeArea()
                
                VStack {
                    HStack {
                        Spacer().frame(maxWidth: 300)
                        Button(action: {
                            print("Settings tapped")
                        }) {
                            Image("settings")
                                .resizable()
                                .background(Color.clear)
                                .frame(width: 37, height: 37)
                        }
                    }
                    
                    Image(chickenImageName)
                        .resizable()
                        .background(Color.clear)
                        .frame(width: 350, height: 350)
                    
                    ScrollView(.horizontal, showsIndicators: false) {
                        HStack(spacing: -10) {
                            if numOfEggs == 0 {
//                                HabitEggButton(habit: false, habitName: "MyHabit", isDisplayed: true)
//                                    .opacity(0)
                                    Text("oops")
                            } else {
                                
                                ForEach($habits) { $habit in
                                    HabitEggButton(habit: $habit)
                                }
                            }
                        }
                    }
                    .offset(x: 25)
                    
                    Text(displayHabit)
                        .font(Font.custom("Inika-Bold", size: 26))
                        .opacity(displayHabit == "" ? 0 : 1)
                        .offset(y: 50)
                }
                .offset(y: -65)
            }
            .navigationBarHidden(true)
        }
    }
}


#Preview {
    ContentView()
}

我尝试过交换 @Binding 和 @State 值,并且我已经使用 print 语句调试了按住按钮。我看到“isDisplayed”值确实发生了变化,但视图没有重新渲染。我认为因为habitEggButton中的习惯对象是@Binding,所以contentView会在值更改后刷新。任何帮助都会很棒,谢谢!

swift swiftui
1个回答
0
投票

其实你说得很好,但我真的不明白为什么你觉得这不令人耳目一新。因为如果您尝试在 ZStack 中添加此行代码,您将看到它已经在观察的变化。

           if habits.contains(where: { $0.isDisplayed == false  }) {
                Color(#colorLiteral(red: 0.7450980544, green: 0.1568627506, blue: 0.07450980693, alpha: 1)).ignoresSafeArea()
            } else {
                Color(#colorLiteral(red: 0.9294117647, green: 0.9294117647, blue: 0.9137254902, alpha: 1)).ignoresSafeArea()
            }
© www.soinside.com 2019 - 2024. All rights reserved.