SwiftUI 将值从几何阅读器传递给函数
Posted
技术标签:
【中文标题】SwiftUI 将值从几何阅读器传递给函数【英文标题】:SwiftUI Pass Value from Geometry Reader to Function 【发布时间】:2020-03-03 20:19:57 【问题描述】:我有一个视图,它使用 Geometry Reader 来计算图像区域的大小:
GeometryReader metrics in
ZStack
self.image
.resizable()
.frame(width: (metrics.size.height - 10) * 0.561403509 , height: metrics.size.height - 10, alignment: .top)
.clipped()
但我有一个函数,我想使用 GeometryReader 计算的帧高度和宽度来裁剪图像。
我有一个单独的函数,可以在按下按钮时裁剪图像:
DownloadImageButton(prepareImagefunction: self.prepareImage() )
然后调用 prepareImage 函数:
func prepareImage( )
// In order for image cropping to work, we need the equivalent of view.bounds in order to adjust the crop so that it correctly measures the crop area. We need metrics.width and metrics.height
var adjustmentScaleForDisplaySize = targetSize.width / metrics.width
请注意,GeometryReader 是调用 prepareImage 的父视图的子视图。因此,理想情况下,子节点会将指标值保存在 EnvironmentObject 或绑定到父节点中。
【问题讨论】:
您能否添加一个示例来说明您要完成的工作,即使它不起作用?metric
可以像任何其他变量一样传递给函数,但不清楚您要做什么。
感谢您的评论。我已经编辑了答案。当图像显示在屏幕上时,我需要保存 metrics.size 以便稍后在父视图的图像裁剪功能中使用它。如果您考虑图像裁剪,通常您使用 view.bounds 来确定裁剪区域。这是等效的要求。
【参考方案1】:
有没有办法将 GeometryReader 计算的值传递给函数?
是的,您可以这样做。 var metrics
是 GeometryProxy
,所以函数签名应该如下例所示
private func resizedImage(for metrics: GeometryProxy) -> some View
self.image
.resizable()
.frame(width: (metrics.size.height - 10) * 0.561403509 , height: metrics.size.height - 10, alignment: .top)
.clipped()
所以你的用法
GeometryReader metrics in
ZStack
self.resizedImage(for: metrics)
更新:更改请求
假设您在子视图中绑定为
@Binding var cropSize: CGSize
上面的函数可以修改如下
private func resizedImage(for metrics: GeometryProxy) -> some View
let size = CGSize(width: (metrics.size.height - 10) * 0.561403509,
height: metrics.size.height - 10)
self.cropSize = size
return self.image
.resizable()
.frame(width: size.width, height: size.height, alignment: .top)
.clipped()
【讨论】:
这真的很棒。但我想做的是将度量值传递给图像裁剪函数。因此,我需要捕获度量高度,例如,以便将其用于裁剪功能。我会附加我的问题,但你的答案肯定接近我的要求! 我现在已经测试过了,self.cropSize = size 会抛出一个错误:[SwiftUI] Modifying state during view update,这会导致未定义的行为。裁剪大小不会传递给父级。 @dot3,它取决于cropSize
和body
构造的使用顺序(未显示),无论如何这不是危急情况,通常已知的解决方案是使其异步,喜欢:DispatchQueue.main.async self.cropSize = size
【参考方案2】:
由于我实际上只需要裁剪大小,并且不一定需要返回图像,因此我执行了以下操作,这也有助于避免在接受的答案中出现错误:
[SwiftUI] Modifying state during view update, this will cause undefined behavior.
我添加了一个 .onAppear 函数调用,有助于避免上述错误,然后将裁剪尺寸正确传递给父级:
GeometryReader metrics in
ZStack
self.image
.resizable()
.frame(width: (metrics.size.height - 10) * 0.561403509 , height: metrics.size.height - 10, alignment: .top)
.clipped()
.onAppear
self.saveCropSize(for: metrics)
....
private func saveCropSize(for metrics: GeometryProxy)
let size = CGSize(width: (metrics.size.height - 10) * 0.561403509,
height: metrics.size.height - 10)
self.cropSize = size
【讨论】:
【参考方案3】:我提出了一个我认为有用的解决方案,使用了一种新类型:
public struct GeometryPasser: View
private let op: (GeometryProxy) -> Void
public init(_ op: @escaping (GeometryProxy) -> Void)
self.op = op
public var body: some View
GeometryReader proxy in
Color.clear.onAppear
op(proxy)
extension View
public func passGeometry(_ op: @escaping (GeometryProxy) -> Void) -> some View
self.background(
GeometryPasser(op)
)
然后像这样调用:
Rectangle()
.fill(.yellow)
.passGeometry geo in
print("do whatever you want here: \(geo)")
【讨论】:
以上是关于SwiftUI 将值从几何阅读器传递给函数的主要内容,如果未能解决你的问题,请参考以下文章
如何将值从 javascript 函数传递到 django 视图
如何将值从 v-select 传递给方法 - 它始终与默认值相同
将值从 Azure 逻辑应用程序传递到 HttpTrigger Azure 函数
如何将值从 javascript 传递到 iOS UIWebView