I have a picker that let's the user choose an image from their photo library. This is presented in a sheet, that's within another sheet that captures user data and saves it with core data.
When the user picks the image I am thrown the warning:
Modifying state during view update, this will cause undefined behavior
I believe it stems from the function below in the view that modifies the state.
How can I move this function out of the view?
if (showCaptureImageView) {
CaptureImageView(isShown: $showCaptureImageView, image: $image)
}
Full code
import SwiftUI
import UIKit
struct CaptureImageView {
@Binding var isShown: Bool
@Binding var image: Image?
func makeCoordinator() -> Coordinator {
return Coordinator(isShown: $isShown, image: $image)
}
}
extension CaptureImageView: UIViewControllerRepresentable {
func makeUIViewController(context: UIViewControllerRepresentableContext<CaptureImageView>) -> UIImagePickerController {
let picker = UIImagePickerController()
picker.delegate = context.coordinator
return picker
}
func updateUIViewController(_ uiViewController: UIImagePickerController,
context: UIViewControllerRepresentableContext<CaptureImageView>) {
}
}
struct addBookView: View {
@Environment(\.managedObjectContext) var moc
@Environment(\.presentationMode) var presentationMode
@State private var title = ""
@State private var author = ""
@State private var currentPage = ""
@State private var image: Image? = nil
@State var showCaptureImageView: Bool = false
var body: some View {
NavigationView {
Form {
Section {
TextField("What's the book title", text: $title)
TextField("Who's the author", text: $author)
TextField("What page are you on", text: $currentPage)
}
Section {
Button (action: {
self.showCaptureImageView.toggle()
}) {
Text("Take a picture")
}
.sheet(isPresented: $showCaptureImageView) {
CaptureImageView(isShown: self.$showCaptureImageView, image: self.$image)
}
image?.resizable()
.frame(width: 250, height: 250)
.clipShape(Circle())
.overlay(Circle().stroke(Color.white, lineWidth: 4))
.shadow(radius: 10)
if (showCaptureImageView) {
CaptureImageView(isShown: $showCaptureImageView, image: $image)
}
}
Section {
Button ("Save") {
let newBook = Book(context: self.moc)
newBook.title = self.title
newBook.author = self.author
newBook.currentPage = self.currentPage
try? self.moc.save()
self.presentationMode.wrappedValue.dismiss()
}
}
}
}
.navigationBarTitle("Add a book")
}
}
struct addBookView_Previews: PreviewProvider {
static var previews: some View {
addBookView()
}
}
Coordinator
import SwiftUI
class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
@Binding var isCoordinatorShown: Bool
@Binding var imageInCoordinator: Image?
init(isShown: Binding<Bool>, image: Binding<Image?>) {
_isCoordinatorShown = isShown
_imageInCoordinator = image
}
func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
guard let unwrapImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage else { return }
imageInCoordinator = Image(uiImage: unwrapImage)
isCoordinatorShown = false
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
isCoordinatorShown = false
}
}