質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.50%
iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

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

Q&A

1回答

1684閲覧

SWIFT メモ帳アプリ 保存の仕方

watchdogs

総合スコア54

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

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

0グッド

0クリップ

投稿2020/07/10 19:40

編集2022/01/12 10:55
コード ```保存ができなくて困っています。 メモ帳アプリを作成しています。 UIには1画面に4つカテゴリ別のテキストフィールドがあります。 保存すると一つしか保存ができず、次回開くとその記録された一つが他のテキストフィールドに記載されてしまっている状態です。 下記プログラム参照して下さい。 具体的にNote2が noteContentxtFieTextViewとNote1に書きかわり保存されてしまっています。 ```ここに言語を入力 import UIKit import Foundation class DisplayNoteViewController: UIViewController,UIImagePickerControllerDelegate,UINavigationControllerDelegate,UITextFieldDelegate { @IBOutlet weak var noteTitleTextField: UITextField! @IBOutlet weak var noteContentxtFieTextView: UITextView! @IBOutlet weak var Note1: UITextView! @IBOutlet weak var Note2: UITextView! @IBOutlet weak var ImageView: UIImageView! @IBOutlet weak var label1: UILabel! @IBOutlet weak var label2: UILabel! @IBOutlet weak var label3: UILabel! @IBOutlet weak var label4: UILabel! var note: Note? override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. } override func viewWillAppear(_ animated: Bool){ super.viewWillAppear(animated) /* noteプロパティの値をアンラップし、実際の値をnoteという名前のローカル変数 に格納するために、オプションのバインディング手法を使用。 */ if let note = note { /* noteプロパティがnilでない場合にのみ実行される。 テキストフィールドとテキストビューのプロパティをnoteの タイトルと内容にそれぞれ設定。 */ noteTitleTextField.text = note.title noteContentxtFieTextView.text = note.content Note1.text = note.content Note2.text = note.content } else { /* noteプロパティがnilの場合に実行される。 新しいノートを作成する際に呼ばれる。 テキストフィールドとテキストビューを空の文字列に設定し、 ユーザーが新しいノートに入力できるようにする。 */ noteTitleTextField.text = "" noteContentxtFieTextView.text = "" Note1.text = "" Note2.text = "" } /* *下記のコードは上記の if let / else と同じ意味 noteTitleTextField.text = note?.title ?? "" noteContentTextView.text = note?.content ?? "" */ } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { let notesTableViewController = segue.destination as! NotesTableViewController if segue.identifier == "save" { if let note = note { /* noteのプロパティがnilでない場合(ノートのタイトルと内容を更新するだけで良い場合)、実行される。 */ note.title = noteTitleTextField.text ?? "" note.content = noteContentxtFieTextView.text ?? "" note.content = Note1.text ?? "" note.content = Note2.text ?? "" // データをリロードするようテーブルビューに指示。 // これにより、作成した既存ノートの編集内容がノート一覧に反映される。 notesTableViewController.tableView.reloadData() } else { // noteのプロパティがnilであれば実行される。(ノートが新規生成される) let newNote = Note() newNote.title = noteTitleTextField.text ?? "" newNote.content = noteContentxtFieTextView.text ?? "" newNote.content = Note1.text ?? "" newNote.content = Note2.text ?? "" notesTableViewController.notes.append(newNote) } } } }
import UIKit class NotesTableViewController: UITableViewController { /* notesプロパティが変更されるたびに、すべてのデータをリロードするように didSetプロパティオブザーバを用いてテーブルビューに通知 */ var notes = [Note]() { didSet { tableView.reloadData() } } override func viewDidLoad() { super.viewDidLoad() // Uncomment the following line to preserve selection between presentations // self.clearsSelectionOnViewWillAppear = false // Uncomment the following line to display an Edit button in the navigation bar for this view controller. // self.navigationItem.rightBarButtonItem = self.editButtonItem() } // 表示すべきセルの数を返す override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return notes.count } // テーブルの特定の行に対して、表示すべきcellを返す // indexPathは、作成するcellがデーブルビュー内のどのセクションと行に属するかを示す override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { //テーブルビューに表示される実際のcellをフェッチしている //ダウンキャスト <- NotesTableViewCellがUITableViewCellのサブクラスであるため機能する //コンパイラに具体的な種類のUITableViewCellを返すことを指示する let cell = tableView.dequeueReusableCell(withIdentifier: "notesTableViewCell", for: indexPath) as! NotesTableViewCell // indexPathは、cellForRowに渡された引数であり、テーブルビューがセルをどの行に表示するのかを示す // indexPathのrowプロパティにアクセスし、検索する。 let row = indexPath.row let note = notes[row] cell.noteTitleLabel.text = note.title return cell } // commitEditingStyle : forRowAt indexPath: により、テーブルビューに追加の編集モードを有効にする // cellを左スワイプした際に削除オプションが表示される override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { // editingStyleが.deleteであるかどうかを調べる if editingStyle == .delete { // notesPathから渡されたindexPathのrowプロパティを使用して、選択されたノートをnotes配列から削除する notes.remove(at: indexPath.row) } } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if let identifier = segue.identifier { if identifier == "displayNote" { print("Table view cell tapped") // すべてのテーブルビューは、indexPathForSelecedRowというプロパティを持っている。 // ユーザーがテーブルビューからcellを選択した場合、特定のcellのindexPathにアクセス可能 // indexPathにはsection,rowのプロパティがあり、選択したテーブルビューのcellをマッピングする // データモデル(ここではnotes配列)に関連付けることができる。 let indexPath = tableView.indexPathForSelectedRow! // テーブルビューにはsectionが1つしかないため、対応するindexPathのrowプロパティを使用して // 各cellを一意に識別できる。 // indexPath.rowで、タッチされたcellに対応するnotes配列からノートを取り出す。 let note = notes[indexPath.row] // ダウンキャスト // segueのdestinationプロパティを使用して、DispalyNoteViewControllerにアクセス let displayNoteViewController = segue.destination as! DisplayNoteViewController // DisplayNoteViewControllerのnoteプロパティを、ユーザーがタッチしたcellに対応するnoteに設定 displayNoteViewController.note = note } else if identifier == "addNote" { print("+ button tapped") } } } @IBAction func unwindToNotesViewController(_ segue: UIStoryboardSegue) { } } ```ここに言語を入力 import Foundation class Note { var title = "" var content = "" }

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

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

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

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

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

guest

回答1

0

swift

1note.content = noteContentxtFieTextView.text ?? "" 2note.content = Note1.text ?? "" 3note.content = Note2.text ?? ""

ここで note.contentnoteContentxtFieTextView.text を入れてそれを Note1.text で上書きしてさらに Note2.text で上書きしているからでは?
同様にviewWillAppearでも1つのインスタンスに対して上書きし続けているようですが、別のインスタンスに分けるとか、配列にするとか、クラスにするとかしないといけないと思います。

プロパティと同名の変数が出てきたりしてコードが非常に読みづらいのと、実際の保存処理のところが提示されていないのでなんとも言えないところではありますが。

追記 Jul 16, 2020 11:00 AM

「データの管理をする」と「データを画面に表示する」の2つの処理について、役割を分けたほうがよいです。
リスト表示画面 (NotesTableViewController) で生成した Note のインスタンスを詳細表示・編集画面 (DisplayNoteViewController) に渡したり、あるいは施した編集作業をリストに反映させるために詳細表示・編集画面からリスト表示画面に渡したり、というのはコードの見通しが良くないです。
下記はシングルトンを使ってデータの管理をするクラス (StoredNotesManager) を実装する例です。実際に動かしてはいませんので適宜調整が必要だとは思いますが、参考になればと思います。

swift

1class Note { 2 var title: String = "" 3 var content: String = "" 4 var memo1: String = "" 5 var memo2: String = "" 6} 7 8class StoredNotesManager { 9 static let shared = StoredNotesManager() 10 private var storedNotes: [Note] = [] 11 private init() { 12 // FIXME: 永続化済みのデータがあればここで storedNotes に格納する 13 } 14 15 var count: Int { 16 get { return self.storedNotes.count } 17 } 18 19 func append(_ appendingNote: Note) -> Void { 20 self.storedNotes.append(appendingNote) 21 self.persistence() 22 } 23 24 func remove(at: Int) -> Void { 25 self.storedNotes.remove(at: at) 26 self.persistence() 27 } 28 29 func update(at: Int, newNote: Note) -> Void { 30 self.storedNotes[at] = newNote 31 self.persistence() 32 } 33 34 func get(at: Int) -> Note? { 35 if self.storedNotes.count <= at { return nil } 36 return self.storedNotes[at] 37 } 38 39 /// 永続化 40 private func persistence() { 41 // FIXME: 永続化処理を実装する 42 } 43}

swift

1// MARK: - 永続化済みの Notes を一覧表示する 2class NotesTableViewController: UITableViewController { 3 override func viewDidLoad() { 4 super.viewDidLoad() 5 } 6 7 // 表示すべきセルの数を返す 8 override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 9 return StoredNotesManager.shared.count 10 } 11 12 // テーブルの特定の行に対して、表示すべきcellを返す 13 // indexPathは、作成するcellがデーブルビュー内のどのセクションと行に属するかを示す 14 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 15 //テーブルビューに表示される実際のcellをフェッチしている 16 //ダウンキャスト <- NotesTableViewCellがUITableViewCellのサブクラスであるため機能する 17 //コンパイラに具体的な種類のUITableViewCellを返すことを指示する 18 let cell = tableView.dequeueReusableCell(withIdentifier: "notesTableViewCell", for: indexPath) as! NotesTableViewCell 19 20 // indexPathは、cellForRowに渡された引数であり、テーブルビューがセルをどの行に表示するのかを示す 21 // indexPathのrowプロパティにアクセスし、検索する。 22 cell.noteTitleLabel.text = StoredNotesManager.shared.get(at: indexPath.row)?.title ?? "" 23 24 return cell 25 } 26 27 // commitEditingStyle : forRowAt indexPath: により、テーブルビューに追加の編集モードを有効にする 28 // cellを左スワイプした際に削除オプションが表示される 29 override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { 30 // editingStyleが.deleteであるかどうかを調べる 31 if editingStyle == .delete { 32 // notesPathから渡されたindexPathのrowプロパティを使用して、選択されたノートをnotes配列から削除する 33 StoredNotesManager.shared.remove(at: indexPath.row) 34 } 35 } 36 37 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 38 if let identifier = segue.identifier { 39 if identifier == "displayNote" { 40 print("Table view cell tapped") 41 42 // すべてのテーブルビューは、indexPathForSelecedRowというプロパティを持っている。 43 // ユーザーがテーブルビューからcellを選択した場合、特定のcellのindexPathにアクセス可能 44 // indexPathにはsection,rowのプロパティがあり、選択したテーブルビューのcellをマッピングする 45 // データモデル(ここではnotes配列)に関連付けることができる。 46 let indexPath = tableView.indexPathForSelectedRow! 47 (segue.destination as! DisplayNoteViewController).storedAt = indexPath.row 48 } else if identifier == "addNote" { 49 print("+ button tapped") 50 (segue.destination as! DisplayNoteViewController).isNewNote = true 51 } 52 } 53 } 54 55 @IBAction func unwindToNotesViewController(_ segue: UIStoryboardSegue) { 56 57 } 58} 59 60// MARK: - Note の詳細表示・編集 61class DisplayNoteViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UITextFieldDelegate { 62 @IBOutlet weak var noteTitleTextField: UITextField! 63 @IBOutlet weak var noteContentxtFieTextView: UITextView! 64 @IBOutlet weak var memo1TextView: UITextView! 65 @IBOutlet weak var memo2TextView: UITextView! 66 67 var storedAt: Int = 0 68 var isNewNote: Bool = false 69 70 override func viewDidLoad() { 71 super.viewDidLoad() 72 } 73 74 override func viewWillAppear(_ animated: Bool){ 75 super.viewWillAppear(animated) 76 77 // 新規作成の場合は空文字を入れる 78 if self.isNewNote { 79 self.noteTitleTextField.text = "" 80 noteContentxtFieTextView.text = "" 81 memo1TextView.text = "" 82 memo2TextView.text = "" 83 return 84 } 85 86 // 既存の Note の詳細表示・編集の場合は、永続化済みの Note から値を取得する 87 let note: Note? = StoredNotesManager.shared.get(at: self.storedAt) 88 self.noteTitleTextField.text = note?.title 89 self.noteContentxtFieTextView.text = note?.content 90 self.memo1TextView.text = note?.memo1 91 self.memo2TextView.text = note?.memo2 92 } 93 94 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 95 if segue.identifier != "save" { return } 96 let newNote: Note = Note() 97 newNote.title = self.noteTitleTextField.text ?? "" 98 newNote.content = self.noteContentxtFieTextView.text 99 newNote.memo1 = self.memo1TextView.text 100 newNote.memo2 = self.memo2TextView.text 101 102 if isNewNote { 103 StoredNotesManager.shared.append(newNote) 104 return 105 } 106 107 StoredNotesManager.shared.update(at: self.storedAt, newNote: newNote) 108 } 109}

投稿2020/07/10 21:06

編集2020/07/16 02:10
thyda.eiqau

総合スコア2982

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

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

watchdogs

2020/07/10 21:15

ご回答ありがとうございます。 配列で表記する場合はどのよに記載すればよろしいでしょうか。
thyda.eiqau

2020/07/10 21:33

ご提示のコードの中から類推することは不可能ですので、Noteの定義部分と実際の保存処理のコードを質問本文に追記してご提示いただかない限り、回答できません。
watchdogs

2020/07/10 22:25

更新させていただきました。保存処理のコードを追加いたしました。
thyda.eiqau

2020/07/11 06:34

保存しているようには見えないですが、「保存」というのは、とくに永続化とかはせず単純にその場限りでTableViewに表示するという意味でおっしゃっていますか? あと、Noteの定義部分もお待ちしています
watchdogs

2020/07/15 22:53

返事が遅れまして申し訳ございません。定義を追加しました。 >保存しているようには見えないですが、「保存」というのは、とくに永続化とかはせず単純にその場限りでTableViewに表示するという意味でおっしゃっていますか? タスクを切っても保存している仕様にしたいと思っています。
thyda.eiqau

2020/07/16 01:03

そういう仕様にしたいかどうかではなくて、現状の(ご提示のコード上の)実装がどうなっているかを確認しています。
thyda.eiqau

2020/07/16 01:06

この質問で目指しているところがよくわからないですね……「1画面に4つカテゴリ別のテキストフィールド」があるということは、保存したいデータというのは4種類のテキストデータなのではないかと思うのですが、Noteの定義を見るとタイトルと本文の2つしか無いのですね。4つのテキストフィールドの値をどのようにNote型の値として保持したいのでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問