search
LoginSignup
13

More than 5 years have passed since last update.

posted at

[Swift] UserDefaults に画像を保存するとフリーズした

リリース後のアプリに、フリーズしたり落ちたりする現象が起きる

インストール直後はサクサクと動いているけど、しばらく使っているうちにフリーズし始めるようでした。画面遷移後や、他のアプリから戻ってきたタイミング、画像を保存するタイミングでフリーズすることが時々あり、その頻度は高まっていきます。すると、アプリを閉じることもできず何もできない、というひどい状況に・・・。そしてしばらく待つと落ちます。

常に同じタイミングでフリーズするという訳でもないので、原因を掴むのに時間を要してしまいました。

解決策

色々と試した結果、以下を変更したことでフリーズすることはなくなりました。

(変更前)UIImage を UserDefaults に保存

UserDefaults に3種類の型(String型、Int型、データ型にキャストした UIImage)が混在した Any 型の配列を、配列に入れて保存していました。

var menuArray = [[Any]]()
let img = UIImage(named: "example")!
let menu = ["menuA", 3, ["menuA", 3, UIImagePNGRepresentation(img)! as NSData] as [Any]
menuArray.append(menu)

let ud = UserDefaults.standard
ud.set(menuArray, forKey: "menuArray")

(変更後)UIImage を DocumentsDirectory に保存

UIImage を DocumentsDirectory に保存して、そのファイル名のみを UserDefaults へ保存しました。さらに、Any 型の配列をやめて、辞書型に変更しました。


// ファイルを保存するURLを返す
func getDocumentsDirectory() -> URL {
  let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
  let documentsDirectory = paths[0]
  return documentsDirectory
}

// ファイルに画像を保存する
func saveImageToDocumentsDirectory(image: UIImage, name: String) {
  if let data = UIImagePNGRepresentation(image) {
      let filename = getDocumentsDirectory().appendingPathComponent(name)
      try? data.write(to: filename)
  }
}

let img = UIImage(named: "example")!
saveImageToDocumentsDirectory(image: img, name: "menuImageX.png")

var menuList = [[String: String]]()
var menu = ["name": "menuA", "point": "3", "fileName": "menuImageX.png"
]
menuList.append(menu)

結論

保存する画像枚数は、インストール時は10枚程度から始まり、ユーザーが保存すると何枚でも保存できます。ただ、アプリの内容からして、大体のユーザーは50枚以内に収まると思います。どの程度からフリーズしやすくなるかは分かりませんが、30枚程度でもフリーズしていたので、画像を UserDefaults に保存することは避けた方が良さそうです。

(参考)

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
13