我正在使 Swift 项目适应 SwiftUI。原始项目对 UIImages 进行拖放、绘图和其他一些在 SwiftUI 中无法实现的操作。
下面的代码仅用于解释问题。工作代码: https ://github.com/rolisanchez/TestableDragAndDrop
在该项目中,当用户点击一个按钮时,a@State setChooseImage
变为 true,打开一张工作表,其中向他展示了一系列图像:
.sheet(isPresented: self.$setChooseImage, onDismiss: nil) {
VStack {
Button(action: {
self.setChooseImage = false
self.chosenAssetImage = UIImage(named: "testImage")
self.shouldAddImage = true
}) {
Image("testImage")
.renderingMode(Image.TemplateRenderingMode?.init(Image.TemplateRenderingMode.original))
Text("Image 1")
}
Button(action: {
self.setChooseImage = false
self.chosenAssetImage = UIImage(named: "testImage2")
self.shouldAddImage = true
}) {
Image("testImage2")
.renderingMode(Image.TemplateRenderingMode?.init(Image.TemplateRenderingMode.original))
Text("Image 2")
}
}
}
选择图像后,setChooseImage
设置回false,关闭工作表。图像self.chosenAssetImage
也是一个@State
并设置为所选图像。@State shouldAddImage
也设置为真。这个选择的 UIImage 和 Bool 在我创建的 UIView 中使用,以添加 UIImages。它在 SwiftUI 中是这样调用的:
DragAndDropRepresentable(shouldAddImage: $shouldAddImage, chosenAssetImage: $chosenAssetImage)
添加 UIView 的 UIViewRepresentable 如下:
struct DragAndDropRepresentable: UIViewRepresentable {
@Binding var shouldAddImage: Bool
@Binding var chosenAssetImage: UIImage?
func makeUIView(context: Context) -> DragAndDropUIView {
let view = DragAndDropUIView(frame: CGRect.zero)
return view
}
func updateUIView(_ uiView: DragAndDropUIView, context: UIViewRepresentableContext< DragAndDropRepresentable >) {
if shouldAddImage {
shouldAddImage = false
guard let image = chosenAssetImage else { return }
uiView.addNewAssetImage(image: image)
}
}
}
我知道
updateUIView
只要有一些可能影响视图的更改就会调用。在这种情况下,shouldAddImage
变为 true,从而正确进入if
循环并调用addNewAssetImage
,将图像插入 UIView。这里的问题是在更新绑定之前
updateUIView
被多次调用,并且一直进入if shouldAddImage
循环。shouldAddImage
这意味着它将多次将图像添加到 UIView。我在赋值之前和之后都放了一个断点
shouldAddImage = false
,甚至在通过那一行之后,值仍然是true
。我想要的行为是将
shouldAddImage
立即更改为false,这样即使updateUIView
被多次调用,它也只会进入循环一次,只添加一次图像。