1

I have a custom struct Information. for the property image(string) I want to insert the path of the document directory where the image is saved. When i try to use the UserDefaults to save the struct array, it is saved successfully and also retrieved. But when i use the path to retrieve the image from the document directory it shows the following error: fatal error: unexpectedly found nil while unwrapping an Optional value. And when I use the if-else block to catch the exception, No image is displayed on the tableview. Below is my code:

struct Information{

var image : String
var content : String?
var url : String?

init(image:String,content:String?,url:String?){
    self.image = image
    self.content = content
    self.url = url

}
init(dictionary : [String:String]) {
    self.image = dictionary["image"]!
    self.content = dictionary["content"]!
    self.url = dictionary["url"]!

}

var dictionaryRepresentation : [String:String] {
    return ["image" : image, "content" : content!, "url" : url!]
}

} And my View Controller:

 override func viewDidAppear(_ animated: Bool) {
    savePath()
    loadDefaults()
    tableView.reloadData()
}

func saveDefaults()
{
    let cfcpArray = information.map{ $0.dictionaryRepresentation }
    UserDefaults.standard.set(cfcpArray, forKey: "cfcpArray")
}

func loadDefaults()
{
    information = (UserDefaults.standard.object(forKey: "cfcpArray") as! [[String:String]]).map{ Information(dictionary:$0) }
    for info in information{
        print(info)
    }
}

func savePath(){
    let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
    // Get the Document directory path
    let documentDirectorPath:String = paths[0]
    // Create a new path for the new images folder
    imagesDirectoryPath = documentDirectorPath + "/ImagePicker"
    var objcBool:ObjCBool = true
    let isExist = FileManager.default.fileExists(atPath: imagesDirectoryPath, isDirectory: &objcBool)
    // If the folder with the given path doesn't exist already, create it
    if isExist == false{
        do{
            try FileManager.default.createDirectory(atPath: imagesDirectoryPath, withIntermediateDirectories: true, attributes: nil)
        }catch{
            print("Something went wrong while creating a new folder")
        }
    }
    tableView.reloadData()
}
 func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
    // The info dictionary may contain multiple representations of the image. You want to use the edited.
            guard  let selectedImage = info[UIImagePickerControllerEditedImage] as? UIImage
                       else {
                    fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
                    }
      image = selectedImage
      dismiss(animated: true, completion: nil)
        saveImage()
}

func saveImage(){
    // Save image to Document directory
    var imagePath = Date().description
    imagePath = imagePath.replacingOccurrences(of: " ", with: "")
    imagePath = imagesDirectoryPath + "/\(imagePath).png"
    path = imagePath
 //   print(path!)
    let data = UIImagePNGRepresentation(image)
    let success = FileManager.default.createFile(atPath:path!, contents: data, attributes: nil)
    information.append(Information(image:path!, content:" ", url: " "))
    saveDefaults()
    tableView.reloadData()

}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cellIdentifier = "TableViewCell"
    /*Because you created a custom cell class that you want to use, downcast the type of the cell to your custom cell subclass, MealTableViewCell.*/
    guard  let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier , for: indexPath) as? TableViewCell
        else{
            fatalError("The dequeued cell is not an instance of MealTableViewCell.")
    }

    let info = information[indexPath.row]

   if let data = FileManager.default.contents(atPath: info.image)
   {
    let decodeimage = UIImage(data: data)
    cell.photos.image = decodeimage

    }
   else{
    print("Not displaying image")
    }
  //  cell.photos.image = UIImage(data: data!)

   return cell
}

Any suggestions is really appreciated. Thank you.

4

2 回答 2

0

不要那样做。出于安全原因,文档文件夹的 URL 会定期更改。

保存一个相对路径——或者只是文件名——并在读取数据后获取当前文档的 URL 并附加路径。

注:NSSearchPathForDirectoriesInDomains已过时。使用url(for:in:appropriateFor:create:)和URL相关的APIFileManager

PS:尽管字典初始化程序总是传递非可选值,但为什么是content和可选的?url

于 2017-06-10T19:25:39.760 回答
0

这是工作代码。经测试。函数 getDocumentsURL() -> URL {

    let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]

    return documentsURL

    }

func fileInDocumentsDirectory(filename: String) -> String {
    let fileURL = getDocumentsURL().appendingPathComponent(filename)
    return fileURL.path

}

并保存图像:

 // Save image to Document directory
            var imagePath = Date().description
            imagePath = imagePath.replacingOccurrences(of: " ", with: "")
            imagePath = "/\(imagePath).png"
            let relpath = getDocumentsURL()
            let relativepath = relpath.appendingPathComponent(imagePath)
            let data = UIImagePNGRepresentation(image)
    let success = FileManager.default.createFile(atPath: relativepath.path , contents: data, attributes: nil)
于 2017-06-11T16:27:43.750 回答