2017-06-10 6 views
1

J'ai une structure personnalisée. pour l'image de la propriété (chaîne) Je veux insérer le chemin du répertoire du document où l'image est enregistrée. Lorsque j'essaie d'utiliser UserDefaults pour enregistrer le tableau struct, il est enregistré avec succès et également récupéré. Mais lorsque j'utilise le chemin pour récupérer l'image à partir du répertoire de document, il affiche l'erreur suivante: Erreur irrécupérable: trouvé de manière inattendue nil lors du déballage d'une valeur facultative. Et quand j'utilise le bloc if-else pour attraper l'exception, aucune image ne s'affiche sur la tableview. Ci-dessous mon code:Enregistrement du chemin du document dans le tableau struct struct de l'erreur Userdefaults swift

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!] 
} 

} Et mon contrôleur de vue:

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 
} 

Toutes les suggestions est vraiment apprécié. Je vous remercie.

Répondre

0

Ne faites pas cela. L'URL du dossier de documents change périodiquement pour des raisons de sécurité. Enregistrer un chemin relatif - ou simplement le nom du fichier - et après avoir lu les données, obtenir l'URL des documents en cours et ajouter le chemin.

Note: NSSearchPathForDirectoriesInDomains est obsolète. Utilisez url(for:in:appropriateFor:create:) et l'URL API liées à des FileManager

PS: Pourquoi content et url optionals bien que le dictionnaire initialiseur passe toujours des valeurs non-option?

+0

Merci beaucoup. Le contenu et l'URL ne doivent pas être facultatifs. Pouvez-vous s'il vous plaît me dire comment sauvegarder un chemin relatif ou juste le nom du fichier. Je suis nouveau à rapide et ne veux pas changer le concept du programme. Merci encore – Mitesh

+0

Vous avez 'imagesDirectoryPath' et' "\ (imagePath) .png" '. Enregistrez donc uniquement 'imagePath' et créez' imagesDirectoryPath' après chaque lancement d'application. Puis concaténez les deux chemins partiels comme dans votre code. – vadian

0

Voici le code de travail. Testé. func 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 

} 

Et pour sauver l'image:

// 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)