Я адаптирую проект Swift для SwiftUI. В оригинальном проекте есть перетаскивание на UIImages, рисование и некоторые другие манипуляции, которые невозможны в SwiftUI.
Приведенный ниже код предназначен только для объяснения проблемы. Рабочий код: https://github.com/rolisanchez/TestableDragAndDrop
В проекте, когда пользователь нажимает кнопку, значение @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
также имеет значение true. Эти выбранные UIImage и Bool используются внутри UIView, который я создал, чтобы добавить UIImage. Он вызывается внутри SwiftUI следующим образом:
DragAndDropRepresentable(shouldAddImage: $shouldAddImage, chosenAssetImage: $chosenAssetImage)
UIViewRepresentable для добавления UIView выглядит следующим образом:
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
стало истинным, таким образом, правильно введя if
l oop и вызвав addNewAssetImage
, который вставляет изображение в UIView.
Проблема здесь в том, что updateUIView
вызывается несколько раз и вводит if shouldAddImage
l oop все это время до обновления shouldAddImage
Binding. Это означает, что он добавит изображение несколько раз в UIView.
Я установил точку останова до и после присвоения shouldAddImage = false
, и даже после прохождения этой строки значение по-прежнему будет true
.
Мне нужно было сразу изменить значение shouldAddImage
на false, чтобы, даже если updateUIView
вызывалось несколько раз, он вводил бы l oop только один раз, добавляя изображение только один раз.