ファイルから画像を読み込むアプリでうまく画像表示できない事がありました。
class ViewController: UIViewController { var imageView = UIImageView() override func viewDidLoad() { super.viewDidLoad() // 画像をファイルに保存 let path = "\(NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])/test" if let originalImage = UIImage(named: "image") { let path = "\(NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])/test" let data = UIImagePNGRepresentation(originalImage) try? data?.write(to: URL(fileURLWithPath: path), options: [.atomic]) } // 画像をファイルから読み込み let image = UIImage(contentsOfFile: path) imageView = UIImageView(image: image) imageView.backgroundColor = UIColor.white view.addSubview(imageView) } }
下は正常な表示です。
画像読み込みが失敗したのは下のようなケースです。
画像読み込み後に元ファイルを削除すると、画像が表示されなくなりました。
class ViewController: UIViewController { var imageView = UIImageView() override func viewDidLoad() { super.viewDidLoad() // 省略… // ファイルを削除 try? FileManager.default.removeItem(atPath: path) } }
次のように何も表示されなくなります。
ファイルの削除をviewDidAppearにしたら問題なく画像表示できました。
class ViewController: UIViewController { var imageView = UIImageView() // 省略… override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) let path = "\(NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])/test" try? FileManager.default.removeItem(atPath: path) } }
viewWillAppearでファイルを削除した場合は画像表示できませんでした。
おそらく画面描画のタイミングでファイルを読み込んでいるため、画面描画前であるviewWillAppear
で削除すると画像読み込みが失敗するのだと思います。
class ViewController: UIViewController { var imageView = UIImageView() // 省略… override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) let path = "\(NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])/test" try? FileManager.default.removeItem(atPath: path) } }
ちなみに公式ドキュメントによると、ファイルのリロード処理が走る事があるようです。
そのため、viewDidAppear
で削除してもリロード処理が走ったら画像が表示されない可能性があります。
init(contentsOfFile:) - UIImage | Apple Developer Documentation
Discussion This method loads the image data into memory and marks it as purgeable. If the data is purged and needs to be reloaded, the image object loads that data again from the specified path.
対策
今回は、Data型を経由する事で対策しました。
次のようにファイルからData形式で読み込んで、それをUIImageに渡しました。
class ViewController: UIViewController { var imageView = UIImageView() override func viewDidLoad() { super.viewDidLoad() // 画像をファイルに保存 let path = "\(NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])/test" if let originalImage = UIImage(named: "image") { let path = "\(NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])/test" let data = UIImagePNGRepresentation(originalImage) try? data?.write(to: URL(fileURLWithPath: path), options: [.atomic]) } // 画像をファイルから読み込み if let data = try? Data(contentsOf: URL(fileURLWithPath: path)) { let image = UIImage(data: data) imageView = UIImageView(image: image) imageView.backgroundColor = UIColor.white view.addSubview(imageView) } // ファイルを削除 try? FileManager.default.removeItem(atPath: path) } }
これで無事に画像表示できるようになりました。