I have a SwiftUI app that is using an image picker wrapped in UIViewControllerRepresentable
using the .sheet
modifier to display it.
Upon picking the image, the rest of the app more or less grinds to a halt until there is some kind of crash in the background, and everything becomes fast again - more info to follow after the code:
import SwiftUI
struct StylePanel: View {
@Binding var image: Image?
@State var inputImage: UIImage? = nil
@State var showImagePicker: Bool
func loadImage() {
guard let inputImage = inputImage else { return }
image = Image(uiImage: inputImage)
}
var body: some View {
VStack {
// Rest of view not shown
Button(action: {
self.showImagePicker = true
}, label: {
Text("Choose image...")
})
}
.sheet(isPresented: self.$showImagePicker, onDismiss: loadImage){
ImagePicker(image: self.$inputImage)
}
}
}
ImagePicker.swift
:
import SwiftUI
struct ImagePicker: UIViewControllerRepresentable {
@Environment(\.presentationMode) var presentationMode
@Binding var image: UIImage?
func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
let picker = UIImagePickerController()
picker.delegate = context.coordinator
return picker
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {
}
func makeCoordinator() -> ImagePickerCoordinator {
return ImagePickerCoordinator(self)
}
}
class ImagePickerCoordinator: 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.image = uiImage
}
parent.presentationMode.wrappedValue.dismiss()
}
}
Once the image is selected, it displays fine in the parent, but other actions such as dragging or modifying state are really janky. The app is very unresponsive until eventually something strange happens – there is some kind of viewServiceDidTerminateWithError
crash in the background and everything starts to behave perfectly again, performance returns to normal. Subsequent reloads of the image picker make it even worse until the same thing happens – background crash followed by normal performance.
This is the error after which performance returns to normal:
[ServicesDaemonManager] interruptionHandler is called. -[FontServicesDaemonManager connection]_block_invoke
[xpc] XPC error talking to pkd: Connection interrupted
[lifecycle] [u 123223B6-8A6C-4BC3-9908-269FA8A8B9E6:m (null)] [com.apple.mobileslideshow.photo-picker(1.0)] Connection to plugin interrupted while in use.
[lifecycle] [u 123223B6-8A6C-4BC3-9908-269FA8A8B9E6:m (null)] [com.apple.mobileslideshow.photo-picker(1.0)] Connection to plugin invalidated while in use.
viewServiceDidTerminateWithError:: Error Domain=_UIViewServiceInterfaceErrorDomain Code=3 "(null)" UserInfo={Message=Service Connection Interrupted}
[Generic] -[PUPhotoPickerHostViewController viewServiceDidTerminateWithError:] Error Error Domain=_UIViewServiceInterfaceErrorDomain Code=3 "(null)" UserInfo={Message=Service Connection Interrupted}
It does seem to be directly related to the use of .sheet
. When I put the Picker directly in the containing view, it works fine without any issues.
What I'd like to know is how I can properly dispose of the UIImagePickerController
modal correctly to stop this performance issue.
Has anyone else experienced this, or know of a solution?