I’m working with UIImagePickerController for the editing feature it offers but I’m running into one slight issue. If I replace the image a few times, about 5-6 it will crash and return warnings like this:
<0x100d08660> Gesture: System gesture gate timed out.
[u 0A3027E7-E344-4002-9629:m (null)] [com.apple.mobileslideshow.photo-picker(1.0)] Connection to plugin interrupted while in use.
[u 0A3027E7-E344-4002-9629:m (null)] [com.apple.mobileslideshow.photo-picker(1.0)] Connection to plugin invalidated while in use.
-[PUPhotoPickerHostViewController viewServiceDidTerminateWithError:] Error Error Domain=_UIViewServiceInterfaceErrorDomain Code=3 "(null)" UserInfo={Message=Service Connection Interrupted}
-[PUPhotoPickerHostViewController viewServiceDidTerminateWithError:] Error Error Domain=_UIViewServiceInterfaceErrorDomain Code=3 "(null)" UserInfo={Message=Service Connection Interrupted}
-[PUPhotoPickerHostViewController viewServiceDidTerminateWithError:] Error Error Domain=_UIViewServiceInterfaceErrorDomain Code=3 "(null)" UserInfo={Message=Service Connection Interrupted}
This is the code:
import SwiftUI
struct ImagePicker: UIViewControllerRepresentable {
var sourceType: UIImagePickerController.SourceType = .photoLibrary
@Binding var selectedImage: UIImage
@Binding var showSheet: Bool
func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
let imagePicker = UIImagePickerController()
imagePicker.allowsEditing = true
imagePicker.sourceType = sourceType
imagePicker.delegate = context.coordinator
let appearance = UINavigationBarAppearance()
appearance.configureWithTransparentBackground()
appearance.backgroundColor = .systemBackground
appearance.titleTextAttributes = [.foregroundColor: UIColor.systemBackground]
appearance.largeTitleTextAttributes = [.foregroundColor: UIColor.systemBackground]
imagePicker.navigationBar.tintColor = .white
imagePicker.navigationBar.standardAppearance = appearance
imagePicker.navigationBar.compactAppearance = appearance
imagePicker.navigationBar.scrollEdgeAppearance = appearance
return imagePicker
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
final class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var parent: ImagePicker
init(_ parent: ImagePicker) {
self.parent = parent
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let image = info[UIImagePickerController.InfoKey.editedImage] as? UIImage {
parent.selectedImage = image
}
parent.showSheet = false
}
}
}
struct ImagePickerTest: View {
@State private var image = UIImage()
@State private var showSheet = false
var body: some View {
VStack {
Button("Change photo") {
showSheet = true
}
Image(uiImage: self.image)
.resizable()
.frame(width: 100, height: 100)
.background(Color.gray)
.scaledToFit()
.clipShape(Circle())
}
.sheet(isPresented: $showSheet) {
ImagePicker(sourceType: .photoLibrary, selectedImage: $image, showSheet: $showSheet)
.ignoresSafeArea(.all)
}
}
}
Not sure where to go from here. This is the first time I’m seeing this.
I’ve used the PhotosPicker from the PhotosUI package and it never fails like this. Only downside is it doesn’t offer an editing mode like UIImagePickerController.
I’m wondering is there some "cleanup" that I need to be doing after I select an image or before I select the next one?
2
Answers
Although I haven’t experienced any crashes with your code even changing the image 10 times, I believe you. I still saw memory usage increase every time I selected a new photo. I guess this is a memory leak. You could try mitigate that by compressing the image you’re loading. To do so you could add this property to your ImagePicker struct:
This will allow you to chose the size of your image.
Then in the
imagePickerController
fuction you apply the actual compression:Also, you will need to update your main View to have a GeometryReader to extract the size from:
Let me know how this works for you and if it still keeps crashing!
It seems like you might be facing memory-related issues with the UIImagePickerController. To address the problem, you can try implementing an additional cleanup step
picker.dismiss
to ensure you release the ImagePicker reference properly anddefer
block will updateshowSheet
before exit.