[英].onAppear() doesn't update Shapes that use @resultBuilder
I was playing around with @resultBuilder
and made a simple result builder called SumBuilder
which takes a bunch of integers and adds them all up.我在玩弄
@resultBuilder
并制作了一个名为SumBuilder
的简单结果生成器,它接受一堆整数并将它们全部相加。
@resultBuilder
struct SumBuilder {
static func buildBlock(_ components: Int...) -> Int {
components.reduce(0, +)
}
}
Since I was also playing around with shapes the other day I thought about creating a custom shape which can use this new result builder in its implementation.因为前几天我也在玩弄形状,所以我想创建一个自定义形状,它可以在其实现中使用这个新的结果生成器。 The custom shape just draws a line from the origin of the container to the point specified.
自定义形状只是从容器的原点到指定点画一条线。
struct CustomShape: Shape {
@SumBuilder let sum: () -> Int
func path(in rect: CGRect) -> Path {
Path { path in
path.move(to: .zero)
path.addLine(to: CGPoint(x: sum(), y: sum()))
}
}
}
When I hooked up sum
to a @State
variable in my ContentView
it works perfectly.当我将
sum
连接到我的ContentView
中的@State
变量时,它工作得很好。 However, when I change sum
using .onAppear()
, the value of sum
will change under the hood but the View
doesn't update to reflect that:但是,当我使用
.onAppear()
更改sum
时, sum
的值将在后台发生变化,但View
不会更新以反映这一点:
struct ContentView: View {
@State private var distance = 0
var body: some View {
VStack {
Button("Increase distance") {
distance += 100
}
CustomShape { distance }
.stroke()
.onAppear { distance = 100 } // << Updates distance, but the View still doesn't show
// the line until I press the Button to make distance = 200
}
}
}
I tried moving the .onAppear()
to the Text
thinking the .onAppear()
wasn't being called since the CustomShape
is initially a dot, but that didn't change anything.我尝试将
.onAppear()
移动到Text
,认为.onAppear()
没有被调用,因为CustomShape
最初是一个点,但这并没有改变任何东西。 What's even stranger is that when I transform the CustomShape
to a regular View
, the .onAppear()
works as intended.更奇怪的是,当我将
CustomShape
转换为常规View
时, .onAppear()
按预期工作。
Does anyone know how to make a Shape
which utilises @resultBuilder
update even when a value is changed using .onAppear()
?有谁知道如何制作一个使用
@resultBuilder
更新的Shape
,即使使用.onAppear()
更改值也是如此? If you can help in any shape or form I'd be very grateful.如果您能以任何形式提供帮助,我将不胜感激。
Thanks in advance!提前致谢!
PS This is only the least amount of code required to recreate the problem. PS 这只是重现问题所需的最少代码。 In my real app I'm initialising a variable called
endPoint
to be the centre using a GeometryProxy
.在我的真实应用程序中,我使用
GeometryProxy
将一个名为endPoint
的变量初始化为中心。 That's why I can't initialise distance
directly when I declare it as it would be conceptually different than what I'm actually trying to achieve.这就是为什么我不能在声明
distance
时直接初始化它,因为它在概念上与我实际尝试实现的不同。
As i mentioned, i just tried your code but using a ViewModel, which worked as expected.正如我所提到的,我只是尝试了您的代码,但使用的是按预期工作的 ViewModel。 In production you probably want to use input-ouput-pattern but this is the least amount of code to explain what i meant by using a ViewModel.
在生产中,您可能想使用输入输出模式,但这是解释我所说的使用 ViewModel 的含义的最少代码。
extension ContentView {
final class ViewModel: ObservableObject {
@Published var distance = 0
}
}
struct ContentView: View {
@StateObject var viewModel = ViewModel()
var body: some View {
VStack {
Button("Increase distance") {
viewModel.distance += 100
}
CustomShape { viewModel.distance }
.stroke()
.onAppear {
viewModel.distance = 100
}
}
}
}
In SwiftUI, the .onAppear()
modifier is used to perform some action when a view appears on the screen.在 SwiftUI 中,
.onAppear()
修饰符用于在视图出现在屏幕上时执行某些操作。 However, this modifier does not trigger a re-render of the view, so any changes made within the.onAppear() closure will not be reflected in the view's appearance.但是,此修饰符不会触发视图的重新渲染,因此在 .onAppear() 闭包中所做的任何更改都不会反映在视图的外观中。
This applies to shapes that use @resultBuilder as well.这也适用于使用 @resultBuilder 的形状。 If a shape is created using @resultBuilder and you make changes to it within the
.onAppear()
closure, the changes will not be visible in the view.如果形状是使用 @resultBuilder 创建的,并且您在
.onAppear()
闭包中对其进行了更改,则更改将不会在视图中可见。 To update a shape that uses @resultBuilder you need to use .onChange()
or .onReceive()
instead of .onAppear()
to update the shape which will trigger the view to re-render.要更新使用 @resultBuilder 的形状,您需要使用
.onChange()
或.onReceive()
而不是.onAppear()
来更新将触发视图重新渲染的形状。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.