🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

保存

保存(save)とは、特定のファイルを、ハードディスク等の外部記憶装置に記録する行為を指します。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

782閲覧

[swift 5]写真を保存すると他の内容に違う写真が反映されてしまっていることで困っている。

Kaguya_4869

総合スコア117

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

保存

保存(save)とは、特定のファイルを、ハードディスク等の外部記憶装置に記録する行為を指します。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

1クリップ

投稿2019/11/23 08:39

編集2019/11/24 09:00

#質問したいこと
語彙力がなくてどう言えばいいのかわからないのですが、写真を保存してからホーム画面へ戻ると他の内容に違う写真が反映されてしまっています。(下記に写真が掲示してあります。)
#コード

swift5

1//追加画面 2import UIKit 3 4class AddViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate { 5 6 @IBOutlet weak var memoTextView: UITextView! 7 @IBOutlet weak var imageView: UIImageView! 8 @IBOutlet weak var imageButton: UIButton! 9 10 let saveData: UserDefaults = UserDefaults.standard 11 12 //カメラボタンがタップされた時の処理 13 @IBAction func launchCamera(_ sender: UIButton) { 14 let camera = UIImagePickerController.SourceType.camera 15 if UIImagePickerController.isSourceTypeAvailable(camera) { 16 let picker = UIImagePickerController() 17 picker.sourceType = camera 18 picker.delegate = self 19 self.present(picker, animated: true) 20 } 21 imageView.isHidden = false 22 imageButton.isHidden = true 23 } 24 25 //ユーザーが撮影し終わった時の処理 26 func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { 27 let image = info[UIImagePickerController.InfoKey.originalImage] as! UIImage 28 self.imageView.image = image 29 UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil) 30 self.dismiss(animated: true) 31 32 UserDefaults.standard.set(image.jpegData(compressionQuality: 0.8), forKey: "MemoImage") 33 saveData.synchronize() 34 } 35 36 override func viewDidLoad() { 37 super.viewDidLoad() 38 39 imageView.isHidden = true 40 } 41 42 @objc func commitButtonTapped() { 43 self.view.endEditing(true) 44 } 45 46 47 48 @IBAction func save(_ sender: Any) { 49 50 let inputText = memoTextView.text 51 let ud = UserDefaults.standard 52 if ud.array(forKey: "memoArray") != nil{ 53 54 var saveMemoArray = ud.array(forKey: "memoArray") as! [String] 55 56 if inputText != ""{ 57 //配列に追加 58 saveMemoArray.append(inputText!) 59 ud.set(saveMemoArray, forKey: "memoArray") 60 }else{ 61 showAlert(title: "何も入力されていません") 62 63 } 64 65 }else{ 66 var newMemoArray = [String]() 67 68 if inputText != ""{ 69 70 newMemoArray.append(inputText!) 71 ud.set(newMemoArray, forKey: "memoArray") 72 }else{ 73 showAlert(title: "何も入力されていません") 74 } 75 } 76 showAlert(title: "保存完了") 77 ud.synchronize() 78 } 79 80 func showAlert(title:String){ 81 let alert = UIAlertController(title: title, message: nil, preferredStyle: .alert) 82 83 alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) 84 85 alert.addAction(UIAlertAction(title: "キャンセル", style: .cancel, handler: nil)) 86 87 self.present(alert, animated: true, completion:nil) 88 } 89 90} 91

swift5

1import UIKit 2 3 4class DetailViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate { 5 6 @IBOutlet weak var memoTextView: UITextView! 7 @IBOutlet weak var imageView: UIImageView! 8 9 var selectedRow:Int! 10 var selectedMemo : String! 11 12 let saveData: UserDefaults = UserDefaults.standard 13 14 //カメラボタンがタップされた時の処理 15 @IBAction func launchCamera(_ sender: UIBarButtonItem) { 16 let camera = UIImagePickerController.SourceType.camera 17 if UIImagePickerController.isSourceTypeAvailable(camera) { 18 let picker = UIImagePickerController() 19 picker.sourceType = camera 20 picker.delegate = self 21 self.present(picker, animated: true) 22 } 23 } 24 25 //ユーザーが撮影し終わった時の処理 26 func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { 27 28 let image = info[UIImagePickerController.InfoKey.originalImage] as! UIImage 29 self.imageView.image = image 30 UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil) 31 self.dismiss(animated: true) 32 UserDefaults.standard.set(image, forKey: "MemoImage") 33 saveData.synchronize() 34 } 35 36 37 38 override func viewDidLoad() { 39 super.viewDidLoad() 40 memoTextView.text = selectedMemo 41 let kbToolBar = UIToolbar(frame: CGRect(x: 0, y: 0, width: 320, height: 40)) 42 kbToolBar.barStyle = UIBarStyle.default // スタイルを設定 43 kbToolBar.sizeToFit() // 画面幅に合わせてサイズを変更 44 // スペーサー 45 let spacer = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: self, action: nil) 46 // 閉じるボタン 47 let commitButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.done, target: self, action: #selector(self.commitButtonTapped)) 48 kbToolBar.items = [spacer, commitButton] 49 memoTextView.inputAccessoryView = kbToolBar 50 51 let imageData:NSData = UserDefaults.standard.object(forKey: "MemoImage") as! NSData 52 imageView.image = UIImage(data: imageData as Data) 53// imageView = saveData.object(forKey: "MemoImage") as! UIImageView 54 } 55 56 @objc func commitButtonTapped() { 57 self.view.endEditing(true) 58 } 59 60 //画面遷移する時にタップするボタン(保存) 61 @IBAction func save(_ sender: Any) { 62 63 let inputText = memoTextView.text 64 let ud = UserDefaults.standard 65 if ud.array(forKey: "memoArray") != nil{ 66 //saveMemoArrayに取得 67 var saveMemoArray = ud.array(forKey: "memoArray") as! [String] 68 //テキストに何か書かれているか? 69 if inputText != ""{ 70 //配列に追加 71 saveMemoArray[selectedRow] = inputText! 72 ud.set(saveMemoArray, forKey: "memoArray") 73 }else{ 74 showAlert(title: "何も入力されていません") 75 76 } 77 78 }else{ 79 //最初、何も書かれていない場合 80 var newMemoArray = [String]() 81 //nilを強制アンラップはエラーが出るから 82 if inputText != ""{ 83 //inputtextはoptional型だから強制アンラップ 84 newMemoArray.append(inputText!) 85 ud.set(newMemoArray, forKey: "memoArray") 86 }else{ 87 showAlert(title: "何も入力されていません") 88 } 89 } 90 showAlert(title: "保存完了") 91 ud.synchronize() 92 } 93 94 func showAlert(title:String){ 95 let alert = UIAlertController(title: title, message: nil, preferredStyle: .alert) 96 97 alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) 98 99 alert.addAction(UIAlertAction(title: "キャンセル", style: .cancel, handler: nil)) 100 101 self.present(alert, animated: true, completion:nil) 102 } 103 //削除ボタン 104 @IBAction func deleteMemo(_ sender: Any) { 105 let ud = UserDefaults.standard 106 if ud.array(forKey: "memoArray") != nil{ 107 var saveMemoArray = ud.array(forKey: "memoArray") as![String] 108 saveMemoArray.remove(at: selectedRow) 109 ud.set(saveMemoArray, forKey: "memoArray" ) 110 ud.synchronize() 111 //画面遷移 112 self.navigationController?.popViewController(animated: true) 113 } 114 } 115 116 //シェアボタン 117 @IBAction func showActivityView(_ sender: UIBarButtonItem) { 118 let activitycontroller = UIActivityViewController(activityItems: [memoTextView], applicationActivities: nil) 119 120 self.present(activitycontroller, animated: true, completion: nil) 121 } 122 123} 124

#写真
ホーム画面
元はこの画像が入っていた
テスト2という新しいメモを作成
テスト1の画像がテスト2の画像と同じ写真になってしまっている

急いでおります。
よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hayabusabusash

2019/11/27 03:41

画像の保存はUserDefaultsで行っているようですが、 もしかして保存する時のキーは"MemoImage"で統一していますか?
Kaguya_4869

2019/11/27 06:15

そうです。memoimageで統一してます。
guest

回答1

0

ベストアンサー

保存する時のキーをMemoImageで統一しているのが原因です。

UserDefaultsはplist形式になっていて、
あるキーに対して値が対応する形になっています。(Key-Value)
なので現状はMemoImageというキーに対して毎回上書きをかけている状態になっていると思います。

もし違う画像を保存したいならMemoImageで統一するのではなく、キーをユニークなものにする必要があると思います。

2019/11/28追記(コードについて)

ちょっと回りくどいかもしれませんが、現状Stringになっているメモを以下のような構造体にします。

Swift

1struct Memo: Codable { 2 let id: String 3 let content: String 4}

contentにはメモの内容を入れて、
idにはUUID().uuidStringを保存して画像の読み込みの時に使用します。
メモを保存する時に、このidをキーとして画像を保存してしまえばメモと画像が紐づく形で保存ができると思います。

Codableに準拠しているので
JSONEncoderJSONDecoderを使用してData型にしたり元のMemoの構造体に戻すことができます。
少し面倒ですが一度Data型として取り出し、その後Memoの配列として取り出すような流れになります。

Swift

1 // AddViewController 2 3 @IBAction func save(_ sender: Any) { 4 let inputText = memoTextView.text 5 6 // 新しいメモの構造体を生成 7 let memo = Memo(id: UUID().uuidString, content: inputText) 8 9 // 一度Dataとして取り出し、そのあとにMemoの配列にデコード 10 if let data = UserDefaults.standard.data(forKey: /*Memoの配列を保存するキー*/), 11 let storedMemoArray = try? JSONDecoder().decode([Memo].self, from: data) { 12 var newMemoArray = storedMemoArray 13 newMemoArray.append(memo) 14 15 // Dataに戻して保存 16 if let newData = try? JSONEncoder().encode(newMemoArray) { 17 UserDefaults.standard.set(newData, forKey: /*Memoの配列を保存するキー*/) 18 } 19 } else { 20 // 何も保存されていなかった時の処理 21 } 22 23 // ImagePickerから選択された画像を取り出し、Dataに変換 24 if let image = imageView.image, 25 let imageData = image.jpegData(compressionQuality: 0.8) { 26 // キーには上で生成したMemoのid(UUID)を使う 27 UserDefaults.standard.set(imageData, forKey: memo.id) 28 } 29 } 30 31 func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { 32 let image = info[UIImagePickerController.InfoKey.originalImage] as! UIImage 33 self.imageView.image = image 34 UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil) 35 self.dismiss(animated: true) 36 37 // ここで保存はせずに、imageViewに選択した画像をセットするだけにします 38 }

保存はこんな感じになると思います。

Memoのidが保存された画像と紐づいているので、
画像の読み込みに特定のMemoのidを使って読みこめば期待する動作になるはずです。

簡単にですがサンプルを作ってみたので、よかったら参考にしてください。

投稿2019/11/27 06:44

編集2019/11/28 11:30
hayabusabusash

総合スコア767

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Kaguya_4869

2019/11/27 09:57

import UIKit class TableViewCell: UITableViewCell { @IBOutlet weak var cellImage: UIImageView! @IBOutlet weak var cellLabel: UILabel! // @IBOutlet weak var label: UILabel! // @IBOutlet weak var tablecell: UITableViewCell! let uuid = NSUUID().uuidString override func awakeFromNib() { super.awakeFromNib() let imageData:NSData = UserDefaults.standard.object(forKey: uuid) as! NSData cellImage.image = UIImage(data: imageData as Data) // Initialization code } override func setSelected(_ selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) // Configure the view for the selected state } //ここを追加 func fill(image: UIImageView, titleLb: String, date: String, siteName: String){ cellImage.image = imageView?.image } } こんな感じで付け足してみたんですけど、Unexpectedly found nil while unwrapping an Optional valueというエラーが出ていて、それが let imageData:NSData = UserDefaults.standard.object(forKey: uuid) as! NSData のコードのところに出ています。 どうすればいいでしょうか
hayabusabusash

2019/11/28 00:34

UUIDは生成する度に違う値になります。 なので保存したときに使ったキーのUUIDは一致せず、UserDefaultsで読み込む際に値を取り出せずにエラーになっている感じですね。 UUIDを使うのはありだと思いますが、 今回の場合メモみたいな情報と一緒に保存する必要があると思います。 なのでメモとUUID等をプロパティとしてもつクラス、もしくは構造体を定義して、それを保存するようにすれば解決できると思います。 クラスの場合はUserDefaultsで保存する場合はデコードの処理が必要になるので注意してください。 構造体でやる場合はCodable準拠にしてData型として扱えばUseDefaultsで保存できるはずです。
Kaguya_4869

2019/11/28 08:25

具体的にどんな感じでコードを書いてみればいいか教えていただけますか? 書き方がよくわからなくて…
hayabusabusash

2019/11/28 11:30

長くなってしまいましたが追記しました!
Kaguya_4869

2019/11/30 06:13

遅くなってしまい、大変申し訳ありませんでした。いつもいつもありがとうございます!!
hayabusabusash

2019/11/30 06:42

解決されたようでよかったです! もしサンプルで不明な点があれば、 Githunbの方でissueとして立ててもらえればいくらでも答えるのでよろしくお願いします????‍♂️
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問