🐷
Swift Realmで画像の保存・表示・削除
Realmを使って画像を保存する2つの方法
Realmには、Image型をそのまま保存できないため、別の何らかの形にして保存してあげる必要があります。
1.ImageをNSData型に変更し保存する
こちらの記事が参考になります。
しかし、私はこちらの記事通りに行っても上手くいきませんでした。(原因は不明...)2.画像をDocumentフォルダに保存し、RealmにはそのファイルURLを保存する
私はこの方法で上手く行きました。そのため、本記事もこの方法を下に実装しています。
stackoverflowを読み漁ったところ、こちらの手段のほうがベストプラクティスだとか。
主にこちらの記事を参考に実装しました。Documentフォルダについての説明もされているので、一度目を通しておくとよいと思います。
Realmに画像を保存する方法
hogeImageViewに表示されている画像を保存します
tableの部分を任意のテーブル名に変えてください
import UIKit
import RealmSwift
class AddImageViewController: UIViewController {
@IBOutlet weak var hogeImageView: UIImageView!
let realm = try! Realm()
// ドキュメントディレクトリの「ファイルURL」(URL型)定義
var documentDirectoryFileURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
// ドキュメントディレクトリの「パス」(String型)定義
let filePath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func addImage(_ sender: UITextField) {
//Realmのテーブルをインスタンス化
let table = Table()
do{
try table.imageURL = directory.documentDirectoryFileURL.absoluteString
}catch{
print("画像の保存に失敗しました")
}
try! realm.write{realm.add(table)}
}
//保存するためのパスを作成する
func createLocalDataFile() {
// 作成するテキストファイルの名前
let fileName = "\(NSUUID().uuidString).png"
// DocumentディレクトリのfileURLを取得
if documentDirectoryFileURL != nil {
// ディレクトリのパスにファイル名をつなげてファイルのフルパスを作る
let path = documentDirectoryFileURL.appendingPathComponent(fileName)
documentDirectoryFileURL = path
}
}
//画像を保存する関数の部分
func saveImage() {
createLocalDataFile()
//pngで保存する場合
let pngImageData = hogeImageView.image?.pngData()
do {
try pngImageData!.write(to: documentDirectoryFileURL)
} catch {
//エラー処理
print("エラー")
}
}
}
これで画像の保存ができます
一部コード解説
try table.imageURL = directory.documentDirectoryFileURL.absoluteString
RealmにはURL型を保存できないため、String型に変更する必要があります
let fileName = "\(NSUUID().uuidString).png"
NSUUID().uuidStringは任意の文字列を生成してくれます
Realmから画像を表示する方法
今、TableのimageURLカラムには、画像の保存先のファイルURLがString型に保存されています
@IBOutlet weak var showImageView: UIImageView!
let realm = try! Realm()
tableData = realm.objects(Table.self)
//URL型にキャスト
let fileURL = URL(string: tableData[0].imageURL)
//パス型に変換
let filePath = fileURL?.path
showImageView.image = UIImage(contentsOfFile: filePath!)
UIImage(contentsOfFile:)の引数は パスである必要があるので注意
ファイルURLとパスの違いについては以下のサイトを参考にしてください
画像の削除について
let realm = try! Realm()
//先程同様にパスを取得
let fileURL = URL(string: tableData[0].imageURL)
let filePath = fileURL?.path
//ファイルの削除
if filePath != nil{
try? FileManager.default.removeItem(atPath: filePath!)
}
try! realm.write{
realm.delete(self.tableData[dataNumber])
}
Documantsフォルダのファイルの削除はこの部分でしています
try! FileManager.default.removeItem(atPath: filePath!)
//ファイルの操作について以下のサイトを参考にしてください
あとがき
調べても古い記事しか出てこず、実装に苦労しました。
この記事がSwiftを学習中の方に役立てばと思います。
不明点あればできる限り返答しますので、気軽にコメントください。
Discussion
mikesanさん、はじめまして。
コメントありがとうございます。
私もmikesanさんと同様の現象が発生したと記憶しております。
残念ですが、解決に至ることができませんでした。
おそらく、シュミレーターを再起動することによって、何らかのデータの不整合が起きてしまっているものだと推測しています。
シュミレーターの仕様もしくは不具合だと割り切って問題ないと思います。(画像をその都度挿入し直すのが、手間ですが...)
お力になれず、申し訳ないです。
私の本番環境(リリース後にアップルストアからダウンロードしたもの)では、問題なく動いていますのでご安心いただけると幸いです。