From the code below everything is working fine except a repetitive delay when opening the image picker (in a sheet) and selecting the image once inside. I end getting the error below when I open the image picker:

<0x103107e90> Gesture: System gesture gate timed out.

And the warning when I pick the image from the picker:

"Error returned from daemon: Error Domain=com.apple.accounts Code=7 "(null)""

I have already added the permission requirements as part of the info.plist file under "Privacy - Photo Library Usage Description" and still have the issue.

This is the image picker and underneath it is the button I am using in the parent view to pull the image picker up as a sheet:

struct ImagePicker: UIViewControllerRepresentable {
    @Binding var selectedImage: UIImage?
    @Environment(\.presentationMode) var presentationMode
    @Binding var choseImageFromCameraRoll: Bool

    class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
        let parent: ImagePicker

        init(parent: ImagePicker) {
            self.parent = parent
        }

        func imagePickerController(
            _ picker: UIImagePickerController,
            didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]
        ) {
            if let uiImage = info[.originalImage] as? UIImage {
                parent.selectedImage = uiImage
                parent.choseImageFromCameraRoll = true
            }
            parent.presentationMode.wrappedValue.dismiss()
        }

        func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
            parent.choseImageFromCameraRoll = false
            parent.selectedImage = nil
            parent.presentationMode.wrappedValue.dismiss()
        }
    }

    func makeCoordinator() -> Coordinator {
        return Coordinator(parent: self)
    }

    func makeUIViewController(context: Context) -> UIImagePickerController {
        let picker = UIImagePickerController()
        picker.delegate = context.coordinator
        picker.sourceType = .photoLibrary
        return picker
    }

    func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {}
}

And below is the button in the main view to pull up the image picker

Button {
                                    if !videoChosen {
                                        isImagePickerPresented = true
                                    }
                                } label: {
                                    Circle()
                                        .frame(width: 60)
                                        .foregroundStyle(.black.opacity(0.5))
                                        .overlay {
                                            Image(systemName: "photo")
                                                .resizable()
                                                .aspectRatio(contentMode: .fit)
                                                .frame(width: 30)
                                                .fontWeight(.medium)
                                                .foregroundStyle(.white)
                                                .opacity(0.85)
                                        }
                                }
                                .padding(.leading, 45)
                                .sheet(isPresented: $isImagePickerPresented) {
                                    ImagePicker(selectedImage: $selectedImage, choseImageFromCameraRoll: $choseImageFromCameraRoll)
                                }
1

There are 1 best solutions below

0
malhal On

Need to change Coordinator(parent: self) to Coordinator() the representable is not an object so can't use self.

Need to implement updateUIViewController to both set a closure on the coordinator that updates the binding and use the current value of the biding to update the view controller, e.g. like this pseudo:

updateUIViewController {
 coordinator.photoPicked = nil
 picker.photo = selectedImage
 coordinator.photoPicked = { photo in
   selectedImage = photo
 }
}