我试图了解如何以及何时调用 .sheet 和 .fullScreenCover 初始值设定项。下面是一个最小的可重现示例,其中第一个屏幕有 3 个彩色矩形,SecondView(通过 .fullScreenCover 显示)有一个矩形根据从第一个屏幕中选择的颜色改变颜色。
- 应用首次加载时,颜色设置为灰色。
- 如果我点击绿色矩形,SecondView 会显示一个灰色矩形。 (即颜色没有正确改变)。
- 如果我随后关闭 SecondView 并点击红色矩形,SecondView 会显示一个红色矩形。 (即颜色 DID 正确更改。)
那么,我想知道为什么这个设置在初始加载时不起作用,但在第 2/3 次尝试时起作用?
注意:我知道这可以通过将“let selectedColor”更改为 @Binding 变量来解决,这不是我要问的。
代码:
import SwiftUI
struct SegueTest: View {
@State var showSheet: Bool = false
@State var color: Color = .gray
var body: some View {
HStack {
RoundedRectangle(cornerRadius: 25)
.fill(Color.red)
.frame(width: 100, height: 100)
.onTapGesture {
color = .red
showSheet.toggle()
}
RoundedRectangle(cornerRadius: 25)
.fill(Color.green)
.frame(width: 100, height: 100)
.onTapGesture {
color = .green
showSheet.toggle()
}
RoundedRectangle(cornerRadius: 25)
.fill(Color.orange)
.frame(width: 100, height: 100)
.onTapGesture {
color = .orange
showSheet.toggle()
}
}
.fullScreenCover(isPresented: $showSheet, content: {
SecondView(selectedColor: color)
})
}
}
struct SecondView: View {
@Environment(\.presentationMode) var presentationMode
let selectedColor: Color // Should change to @Binding
var body: some View {
ZStack {
Color.black.edgesIgnoringSafeArea(.all)
RoundedRectangle(cornerRadius: 25)
.fill(selectedColor)
.frame(width: 300, height: 300)
}
.onTapGesture {
presentationMode.wrappedValue.dismiss()
}
}
}
struct SegueTest_Previews: PreviewProvider {
static var previews: some View {
SegueTest()
}
}
最佳答案
查看注释和print
语句。尤其是红色
import SwiftUI
struct SegueTest: View {
@State var showSheet: Bool = false{
didSet{
print("showSheet :: didSet")
}
willSet{
print("showSheet :: willSet")
}
}
@State var color: Color = .gray{
didSet{
print("color :: didSet :: \(color.description)")
}
willSet{
print("color :: willSet :: \(color.description)")
}
}
@State var refresh: Bool = false
init(){
print("SegueTest " + #function)
}
var body: some View {
print(#function)
return HStack {
//Just to see what happens when you recreate the View
//Text(refresh.description)
Text(color.description)
RoundedRectangle(cornerRadius: 25)
.fill(Color.red)
.frame(width: 100, height: 100)
.onTapGesture {
print("SegueTest :: onTapGesture :: red")
//Changing the color
color = .red
//Refreshed SegueTest reloads function
//refresh.toggle()
showSheet.toggle()
}
RoundedRectangle(cornerRadius: 25)
.fill(Color.green)
.frame(width: 100, height: 100)
.onTapGesture {
print("SegueTest :: onTapGesture :: green")
//Changing the color
color = .green
showSheet.toggle()
}
RoundedRectangle(cornerRadius: 25)
.fill(Color.orange)
.frame(width: 100, height: 100)
.onTapGesture {
print("SegueTest :: onTapGesture :: orange")
//Changing the color
color = .orange
showSheet.toggle()
}
}
//This part is likely created when SegueTest is created and since a struct is immutable it keeps the original value
.fullScreenCover(isPresented: $showSheet, content: {
SecondView(selectedColor: color)
})
}
}
struct SecondView: View {
@Environment(\.presentationMode) var presentationMode
//struct is immutable
let selectedColor: Color // Should change to @Binding
init(selectedColor: Color){
print("SecondView " + #function)
self.selectedColor = selectedColor
print("SecondView :: struct :: selectedColor = \(self.selectedColor.description)" )
print("SecondView :: parameter :: selectedColor = \(selectedColor.description)" )
}
var body: some View {
ZStack {
Color.black.edgesIgnoringSafeArea(.all)
RoundedRectangle(cornerRadius: 25)
.fill(selectedColor)
.frame(width: 300, height: 300)
}
.onTapGesture {
presentationMode.wrappedValue.dismiss()
}
}
}
struct SegueTest_Previews: PreviewProvider {
static var previews: some View {
SegueTest()
}
}
关于SwiftUI:在使用常量与@Binding 初始值设定项时了解 .sheet/.fullScreenCover 生命周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65281559/