SwiftUI PhotoPicker multiple upload causes a loop/animation

50 Views Asked by At

I would like to give the user the option to upload more than 1 image at once via PhotoPicker. When uploading one image at a time, everything is working as expected. As much images as needed can be uploaded, but only one after another.

When changing the maxSelectionCount value to more the 1, like 2 or 4 as an example, the following happens:

Here is the code with the relevant parts:

struct UpdateBonsaiView: View {

  @Environment(\.dismiss) var dismiss
  @Environment(\.modelContext) var context

  @State var bonsai = BonsaiModel()

  @Query private var bonsaiImageModelQuery: [BonsaiImageModel]
  @State var images = BonsaiImageModel()
  @State private var selectedBonsaiImages: [PhotosPickerItem] = []

  var body: some View {
    NavigationView {
      Form {
        Section("Update you Image and select up to X pictures at once.") {

          VStack {
            Section {
              PhotosPicker(selection: $selectedBonsaiImages, maxSelectionCount: 3, selectionBehavior: .ordered, matching: .images, photoLibrary: .shared()) {
                Label("Add Image", systemImage: "photo")
                  .foregroundColor(Color("buttonColor"))
              }
              .padding()
            }

            ScrollView {
              LazyVGrid(columns: [GridItem(.adaptive(minimum: 140))]) {

                ForEach(bonsaiImageModelQuery.filter({ $0.bonsai == bonsai })) { bonsaiImage in

                  ZStack(alignment: .topTrailing) {

                    if let imageData = bonsaiImage.imageData,
                       let uiImage = UIImage(data: imageData){
                      Image(uiImage: uiImage)
                        .resizable()
                        .scaledToFill()
                        .frame(width: 140, height: 100)
                        .clipped()
                    }

                    Button(role: .destructive) {
                      withAnimation {
                        context.delete(bonsaiImage)
                      }
                    } label: {
                      Image(systemName: "xmark")
                        .frame(width: 30, height: 30)
                        .background(Color(.white))
                        .clipShape(RoundedRectangle(cornerRadius: 15))
                        .foregroundStyle(.red)
                    }
                  }
                }
              }
            }
          }
          .onChange(of: selectedBonsaiImages) { _, _ in
            Task {
              for items in selectedBonsaiImages {
                if let data = try? await items.loadTransferable(type: Data.self) {
                  images.bonsai = bonsai
                  images.imageData = data
                }
              }
            }
          }
        }
      }
    }
  }
}

@Model
final class BonsaiImageModel {
  var uuid: UUID
  @Attribute(.externalStorage)
  var imageData: Data?

  var bonsai: BonsaiModel?

  init(data: Data? = nil) {
    self.uuid = UUID()
  }
}

@Model
final class BonsaiModel {
  var uuid: UUID
  var timestamp: Date
  var purchased: Date
  var price: Int
  var name: String
  var isFavorite: Bool
  var age: Int

  @Relationship(deleteRule: .cascade, inverse: \BonsaiImageModel.bonsai)
  var bonsaiImages: [BonsaiImageModel] = []

  init(name: String = "",
       isFavorite: Bool = false
  ) {
    self.uuid = UUID()
    self.timestamp = Date()
    self.purchased = Date()
    self.price = Int()
    self.name = name
    self.isFavorite = isFavorite
    self.age = 2023

  }
}

I update the Model with the selection in a for-loop. It works, but only for one picture, no more.

0

There are 0 best solutions below