Home > Back-end >  UIImageView Array ForEach Iteration Loop problem
UIImageView Array ForEach Iteration Loop problem

Time:09-16

while developing my iOS app I encountered a problem with getting image in Array of UIImageViews to perform an action on that specific image. No matter which picture from my LazyVGrid photo collection I do LongPressGesture action on, it always applies to the first picture which is displayed. I think this might be an issue with the ids in my array that ForEach loop do not recognize each element properly, however I have no idea how to solve it.

I keep my array in ProfileViewModel class:

@Published var userPicturesView: [UIImageView] = [UIImageView]()

And I'm looping through it in my ProfileView:

ScrollView() {
                            LazyVGrid(columns: Array(repeating: GridItem(), count: 3)) {
                                ForEach(0..<profileViewModel.userPicturesView.count, id: \.self) { imageIndex in
                                    if profileViewModel.userPicturesView[imageIndex].image != nil {
                                        Image(uiImage: profileViewModel.userPicturesView[imageIndex].image!)
                                            .resizable()
                                            .border(Color.black, width: 0.25)
                                            .frame(width: screenWidth * 0.34, height: screenHeight * 0.17)
                                            .onLongPressGesture {
                                                withAnimation {
                                                    self.shouldPresentEditActionSheet = true
                                                }
                                            }
                                            .actionSheet(isPresented: $shouldPresentEditActionSheet) {
                                                ActionSheet(title: Text("Edit selected"), message: nil, buttons: [
                                                    .default(Text("Set as profile picture"), action: {
                                                        withAnimation {
                                                            self.profilePictureImage = Image(uiImage: self.profileViewModel.userPicturesView[imageIndex].image!)
                                                        }
                                                    }),
                                                    .destructive(Text("Delete this photo"), action: {
                                                        withAnimation {
                                                            self.profileViewModel.deleteUserImage(imageIndex: imageIndex)
                                                        }
                                                    }),
                                                    .cancel()
                                                ])
                                            }
                                    }
                                }
                            }
                        }

I can add that I tried solving it by adding custom struct that holds my picture:

struct PictureView: Identifiable {
    var id = UUID()
    var uiImageView: UIImageView
    
    init(uiImageView: UIImageView) {
        self.uiImageView = uiImageView
    }
}

and then making an array of this structs in ProfileViewModel like this:

@Published var userPicturesView: [PictureView] = [PictureView]()

Then changing ProfileView in this way:

ScrollView() {
                            LazyVGrid(columns: Array(repeating: GridItem(), count: 3)) {
                                ForEach(self.profileViewModel.userPicturesView) { userPictureView in
                                    if userPictureView.uiImageView.image != nil {
                                        Image(uiImage: userPictureView.uiImageView.image!)
                                            .resizable()
                                            .border(Color.black, width: 0.25)
                                            .frame(width: screenWidth * 0.34, height: screenHeight * 0.17)
                                            .onLongPressGesture {
                                                withAnimation {
                                                    self.shouldPresentEditActionSheet = true
                                                }
                                            }
                                            .actionSheet(isPresented: $shouldPresentEditActionSheet) {
                                                ActionSheet(title: Text("Edit selected"), message: nil, buttons: [
                                                    .default(Text("Set as profile picture"), action: {
                                                        withAnimation {
                                                            self.profilePictureImage = Image(uiImage: userPictureView.uiImageView.image!)
                                                        }
                                                    }),
                                                    .destructive(Text("Delete this photo"), action: {
                                                        withAnimation {
//                                                            self.profileViewModel.deleteUserImage(imageIndex: imageIndex)
                                                        }
                                                    }),
                                                    .cancel()
                                                ])
                                            }
                                    }
                                }
                            }
                        }

But this brought the same result. Every help will be appreciated.

CodePudding user response:

Using actionSheet(item:) instead of actionSheet(isPresented:) will give you access to the selected item. In iOS 14 , there are issues with isPresented rendering a previous value first. Here's a simplified version of your code:

struct ContentView: View {
    let pictureViews : [PictureView] = []
    @State private var selectedItem : PictureView? = nil
    
    var body: some View {
        ForEach(pictureViews) { pictureView in
            Image(uiImage: pictureView.uiImageView.image!)
                .onLongPressGesture {
                    selectedItem = pictureView
                }
        }.actionSheet(item: $selectedItem) { item in
            ActionSheet(title: Text("Edit selected"), message: nil, buttons: [
                .default(Text("Set as profile picture"), action: {
                    withAnimation {
                        //use `item` here
                    }
                }),
                .destructive(Text("Delete this photo"), action: {
                    withAnimation {
                        //use `item` here
                    }
                }),
                .cancel()
            ])
        }
    }
}
  • Related