ImagePicker in SwiftUI

Hi, I have a problem with the following code:
Code Block Swift
struct AddView: View {
  @State var text:String = ""
  @State private var image1 : String?
  @State private var showingPicker = false
  @Binding var listItems: [Item]
  @State private var inputImage : String?
  var body: some View {
     
    VStack{
      TextField("Name", text: $text).padding().background(Color(.systemGray5)).frame(width: 400,alignment: .center).cornerRadius(20)
       
        Image(systemName: "person.circle")
         
        .frame(width: 170, height: 170, alignment: .center)
        .clipShape(Circle())
        .shadow(radius: 10)
        .overlay(Circle()
        .stroke(Color.blue))
        .position(x: 209, y: 100)
        .onTapGesture {
          self.showingPicker = true
           
             
        }.sheet(isPresented: $showingPicker, onDismiss: loadImage){
          ImagePicker(image: self.$inputImage)
           
        }
         
         
       
       
       
       
      Button(action: {
        listItems.append(Item(name: text, image: "Gif"))
        UserDefaults.standard.saveItems(listItems)
        print(listItems)
        
         
         
         
      }, label: {
        Text("Add")
      })
    }
  }
  func loadImage(){
    guard let inputImage1 = inputImage else {
      print(inputImage)
      return
    }
  }
}
extension UserDefaults {
  func saveItems(_ items: [Item]) {
    let encoder = JSONEncoder()
    if let data = try? encoder.encode(items) {
      set(data, forKey: "Items")
    }
  }
}
struct ImagePicker : UIViewControllerRepresentable{
   
  class Coordinator : NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate{
    let parent : ImagePicker
    init(_ parent: ImagePicker){
      self.parent = parent
    }
     
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info:[UIImagePickerController.InfoKey : String]){
      if let uiImage = info[.originalImage]{
        parent.image = uiImage
       
      }
      parent.presentaitionMode.wrappedValue.dismiss()
    }
  }
   
  @Environment(\.presentationMode) var presentaitionMode
  @Binding var image : String?
   
  func makeCoordinator() -> Coordinator {
    Coordinator(self)
  }
   
   
   
  func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController{
    let picker = UIImagePickerController()
    picker.delegate = context.coordinator
    return picker
  }
  func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {
     
  }
}

When I print out the inputImage, it says it is nil. Why is it like this? Can you help me please?

Replies

When I print out the inputImage

Where is the print statement that showed nil?
In the function loadImage in struct AppView
@OOPer In the function loadImage in struct AppView

Now that I checked the imagePickerController(_:didFinishPickingMediaWithInfo:). The info should actually be [UIImagePickerController.InfoKey: Any], not [UIImagePickerController.InfoKey: String]. So that could be where things get weird since you're not matching the type between the ObjC requirement with Swift function.

Also, info[.originalImage] is an UIImage, not String?. Likely you had type mismatch, and the interop with ObjC just silence the error and change to nil.

In the function loadImage in struct AppView

Then it is quite normal as the print statement is in the else-clause of the guard-statement.

If your code shows unexpected behavior, you may need to check other parts of your code.
I think @Lantua's suggestion is hitting the core part of the problem in your code. 
I changed it to a String because I want to save the name of the picture in the UserDefaults. Is there a way to do that?

I changed it to a String because I want to save the name of the picture in the UserDefaults. Is there a way to do that?

You cannot get the name of an image picked by UIImagePickerController.

You may need to create another view to request the name of the image to user, and make a database binding the input name to the picked image.

Or else, you may be able to use imageURL instead of the name.
You can convert the UIImage to Data to store in UserDefaults or somewhere else
Code Block Swift
if let uiImageData = uiImage.jpegData(compressionQuality: 1) {
UserDefaults.standard.set(uiImageData, forKey: "Items")
}
Code Block Swift
if let uiImageData = UserDefaults.standard.data(forKey: "Items") {
uiImage = UIImage(data: uiImageData)
}

Hi, I did what you said me and when I want to add the "inputImage" to the "listItems" Array, I get the error: Cannot convert value of type 'Image?' to expected argument type 'String'. Do I have to change the "image" in the struct "Item" to Data?:

Code Block
struct Item : Identifiable, Codable{
  var id = UUID()
  var name : String
  var birthday : String
  var image : String
   
}





Do I have to change the "image" in the struct "Item" to Data?

If you want to store the content of the UIImage, the answer would be YES.
If you want to store the name of the image, NO.

What do you want to store into image of Item?
I want to store the Image so that I can load the Image later

I want to store the Image so that I can load the Image later

Then the name cannot be your option.
You can save the jpegData (of type Data) if you change the type of image to Data.
Or else, you can make the image of type UIImage, you just need to write some methods to conform to Codable by yourself.

Anyway, saving a few tens of images into UserDefaults might make your app crash or freeze.

You can store imageURL into your Item if you change the type to URL, as already noted.
Hi I converted the image to URL and I get this error when I want to give the URL to AddView, I get the error:

Cannot convert value of type 'Binding<URL>' to expected argument type 'Binding<URL?>'

what can I do there?
You can use
Code Block Swift
Binding(imageUrl)

to convert from Binding<URL> to Binding<URL?>
Hi thank you for your help but the Url i get is "Optional(./ -- file:///)". Do you need some of my code to see what I have to do ?