Search code examples
swiftxcodeimageswiftuinsdocumentdirectory

How do I load this image data from disk and present it in my SwiftUI List?


I have used an imagePicker in SwiftUI to select an image from the user's photo album, and save this image to disk under a unique id. Here is saving the image (as Data):

 func saveImage(imageName: String, image: Data) {

guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }

let fileName = imageName
let fileURL = documentsDirectory.appendingPathComponent(fileName)

//Checks if file exists, removes it if so.
if FileManager.default.fileExists(atPath: fileURL.path) {
    do {
        try FileManager.default.removeItem(atPath: fileURL.path)
        print("Removed old image")
    } catch let removeError {
        print("couldn't remove file at path", removeError)
    }

}

do {
    try image.write(to: fileURL)
    print("Image ID: \(imageName) saved. Data: \(image)")
} catch let error {
    print("error saving file with error", error)
}

}

After this, I want to populate a list, and convert the data back into an Image for use in a List:

struct ListView: View {

//notification viewmodel class
@EnvironmentObject var vm: ViewModel
@State private var inputImage: UIImage?
@State private var image: Image?
@State private var id: String?

func loadImage() {
    guard let inputImage = inputImage else { return }
    image = Image(uiImage: inputImage)
}

func loadImageFromDiskWith(fileName: String) -> UIImage? {

  let documentDirectory = FileManager.SearchPathDirectory.documentDirectory

    let userDomainMask = FileManager.SearchPathDomainMask.userDomainMask
    let paths = NSSearchPathForDirectoriesInDomains(documentDirectory, userDomainMask, true)

    if let dirPath = paths.first {
        let imageUrl = URL(fileURLWithPath: dirPath).appendingPathComponent(fileName)
        let image = UIImage(contentsOfFile: imageUrl.path)
        return image

    }

    return nil
}

var body: some View {
    
    NavigationView {

        List {
            
            //New row for each item in notification array
            ForEach(vm.notificationArray, id: \.content) { notification in
                
                HStack {
                VStack(alignment: .leading, spacing: 10) {
                    //Populate text with info from notification.
                    Text(notification.content.title)
                    let id = notification.identifier
                
                  //I want to call loadImage here, and show the image if it exists, but there are many errors with this and I can't seem to get it to work
                    image = Image(uiImage: loadImageFromDiskWith(fileName: id)!)
            
                    if image != nil {
                        image?
                            .resizable()
                            .scaledToFit()
                    } else {
                    }
                    
            }
         
            }
            }
            
            
    }
    
}
  
    }
}

}

How can I call my load image function and get present the image in the list? Thank you.


Solution

  • Try the following

    VStack(alignment: .leading, spacing: 10) {
        //Populate text with info from notification.
        Text(notification.content.title)
    
        if let image = loadImageFromDiskWith(fileName: notification.identifier) {
            Image(uiImage: image)
                .resizable()
                .scaledToFit()
        } else {
           // Put some placeholder image here
        }
    }