2017-06-10 13 views
1

私はカスタム構造体情報を持っています。プロパティイメージ(文字列)の場合、イメージが保存されるドキュメントディレクトリのパスを挿入します。構造体配列を保存するためにUserDefaultsを使用しようとすると、正常に保存され、取得されます。しかし、パスを使用してドキュメントディレクトリからイメージを取得すると、次のエラーが表示されます。 致命的なエラー:オプション値のアンラッピング中に予期せずnilが見つかりました。 if-elseブロックを使用して例外をキャッチすると、画像がテーブルビューに表示されません。Userdefaultsエラースウィフトでカスタム構造体配列にドキュメントパスを保存する

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

} そして、私のビューコントローラ:

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 
} 

任意の提案は本当に感謝され 以下は私のコードです。ありがとうございました。

答えて

0

しないでください。セキュリティ上の理由から、ドキュメントフォルダのURLが定期的に変更されます。

相対パスまたはファイル名だけを保存し、データを読み込んだ後に現在のドキュメントURLを取得し、パスを追加します。

注:NSSearchPathForDirectoriesInDomainsは古くなっています。 url(for:in:appropriateFor:create:)FileManager

PSのURL関連のAPIを使用してください:辞書初期化子は常に非オプションの値を渡しますが、なぜcontenturl optionalsは?

+0

はありがとうございました。コンテンツとURLはオプションであってはなりません。相対パスを保存するか、ファイル名だけを保存するか教えてください。私は速やかに新しいですし、プログラムのコンセプトを変更したくありません。もう一度ありがとう – Mitesh

+0

あなたは 'imagesDirectoryPath'と' '\(imagePath).png"を得ました。したがって、各アプリケーションの起動後に 'imagePath'のみを保存し、' imagesDirectoryPath'を作成してください。次に、コードのように両方の部分パスを連結します。 – vadian

0

ここに作業コードがあります。テスト済み。 getDocumentsURL FUNC () - > 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)