SwiftUI .onLongPressGesture() необходимо дважды нажать и удерживать, прежде чем произойдет действие

Я практикую swiftUI, создавая небольшое приложение-альбом камеры, которое обращается к фотоальбому, чтобы пользователь мог выбрать и загрузить фотографию в приложение. Затем отображаются загруженные фотографии, поэтому пользователь выбирает фотографию в качестве основной фотографии. Проблема с.onLongPressGesture()модификатор, лист действий отображается, когда пользователь долго нажимает на фотографию, чтобы попросить пользователя обновить выбранную или удалить ее. Удаление работает нормально. Однако, если пользователь выбирает «обновить фотографию», то отображается фотоальбом для выбора новой фотографии, а когда фотография выбрана, она не отображается, а старая фотография по-прежнему отображается. Когда та же фотография снова долго нажимается, наконец отображается новая фотография, и снова отображается список действий. Мне нужно, чтобы фотография обновлялась после того, как пользователь выберет новую фотографию.

Пожалуйста, какие-либо предложения по решению этой проблемы? Код показан ниже, спасибо:

      class EnvImage: ObservableObject {
  @Published var id: UUID
  @Published var imagesArray: [UserImages]

  init() {
    id = UUID()
    imagesArray = []
    self.objectWillChange.send()
  }
}

 class UserImages: Identifiable {
  let id: UUID
  var image: Image
  var isSelected: Bool
  var isLongPressed: Bool

  init(image: Image) {
    id = UUID()
    self.image = image
    isSelected = false
    isLongPressed = false
  }
}

Использование:

      struct ContentView: View {
@StateObject var envImage = EnvImage()

@State private var photo: UIImage = UIImage(systemName: "person.circle")!
@State private var isSelectingPhoto = false
@State private var isShowingActionSheet = false
@State private var isPlusPressed = false
@State private var selectedCardImage: UserImages?
var imageSize: CGFloat = 150
var body: some View {
    VStack {
        
        if let selectedCardImage {
            selectedCardImage.image
                .resizable()
                .scaledToFit()
                .frame(width: imageSize, height: imageSize)
                .cornerRadius(20)
                .padding()
        } else {
            Image(systemName: "person.circle")
                .resizable()
                .scaledToFit()
                .frame(width: imageSize, height: imageSize)
                .cornerRadius(20)
                .padding()
        }
        
        HStack {
            ScrollView(.horizontal) {
                HStack {
                    ForEach(envImage.imagesArray, id: \.id) { image in
                        image.image
                            .resizable()
                            .scaledToFit()
                            .frame(width: imageSize, height: imageSize)
                            .cornerRadius(20)
                            .onTapGesture() { // works fine
                                onTapGesture(image: image) // works fine
                            }
                            .onLongPressGesture(minimumDuration: 1) { // issue: must be longe pressed twice to see photo gets updated
                                onLongGesture(image: image)
                            }                                
                            .padding(10)
                    }
                }
                .padding()
            }
            
            Spacer()
            
            if envImage.imagesArray.count < 3 {
                Button {
                    isSelectingPhoto = true
                    isPlusPressed = true
                } label: {
                    Image(systemName: "plus.circle")
                        .font(.system(size: 40))
                }
            }
        }
    }
    .sheet(isPresented: $isSelectingPhoto) {
        PhotoPicker(vCardImage: $photo)
    }
    .actionSheet(isPresented: $isShowingActionSheet) {
        ActionSheet(title: Text("what would you like to do?"), buttons: [
                                                    .default(Text("update photo"), action: {
                                                        isSelectingPhoto = true
                                                    }),
                                                    .destructive(Text("delete photo"), action: {
                                                        for (index,image) in envImage.imagesArray.enumerated() where image.isLongPressed == true {
                                                            deleteImage(index: index, imageToDelete: image)
                                                        }
                                                    }),
                                                    .cancel()
                                                    ])
    }
    .onChange(of: photo) { _ in
        if isPlusPressed {
            envImage.imagesArray.append(UserImages(image: Image(uiImage: photo)))
            isPlusPressed = false
        } else {
            for image in envImage.imagesArray where image.isLongPressed == true {
                if let tempSelectedCard = selectedCardImage, tempSelectedCard.id == image.id {
                    image.image = Image(uiImage: photo)
                    selectedCardImage = image
                } else {
                    image.image = Image(uiImage: photo)
                }
                    image.isLongPressed = false
                    break
            }
        }
    }
    .padding()
    .preferredColorScheme(.light)
}

func onTapGesture(image: UserImages) {
    selectedCardImage = image
    image.isSelected = true
    for others in envImage.imagesArray where others.id != image.id {
        others.isSelected = false
    }
}

func onLongGesture(image: UserImages) {
    image.isLongPressed = true
    for others in envImage.imagesArray where others.id != image.id {
        others.isLongPressed = false
    }
    isShowingActionSheet = true
}
}

func deleteImage(index: Int, imageToDelete: UserImages) {
    if let tempSelectedCardImage = selectedCardImage, tempSelectedCardImage.id == imageToDelete.id {
        print("same image to delete")
        envImage.imagesArray.remove(at: index)
        selectedCardImage = nil
    } else if let selectedCardImage, selectedCardImage.id != imageToDelete.id {
        print("different image to delete, and selectedCardImage not empty")
        envImage.imagesArray.remove(at: index)
    } else if selectedCardImage == nil {
        print("selectedCardImage is empty")
        envImage.imagesArray.remove(at: index)
    }
}

Спасибо!

Редактировать:

Я редактирую вопрос, потому что нашел временное решение.

The .onLongPressGestureработает как положено, только если значение.imageназначается@State Imageпеременная. В результате я объявил@State private var otherImage = Image(systemName: "person.circle"), и изменил изображение, используя код внутри блока for-loop.onChange(of: photo)функционировать, как показано ниже:

      .onChange(of: photo) { _ in
        if isPlusPressed {
            envImage.imagesArray.append(UserImages(image: Image(uiImage: photo)))
            isPlusPressed = false
        }
        else {
            for image in envImage.imagesArray where image.isLongPressed == true {
                if image.isSelected {
                    print("image is selected")
                    image.image = Image(uiImage: photo)
                    selectedCardImage = image
                    otherImage = image.image
                } else {
                    image.image = Image(uiImage: photo)
                    print("other image is selected")
                    otherImage = image.image
                }
                break
            }
        }
    }
    .padding()
    .preferredColorScheme(.light)

Затем, внутриbodyя далotherImageследующие модификаторы:

      otherImage
    .resizable()
    .scaledToFit()
    .frame(width: 1, height: 1)
    .hidden()

Это не идеальное решение и не уверен, почему использованиеEnvImageиUserImagesне работает как положено!! Любые идеи, пожалуйста?

0 ответов

Другие вопросы по тегам