回答編集履歴

1

追加情報にもとづく追記

2020/07/16 02:10

投稿

thyda.eiqau
thyda.eiqau

スコア2982

test CHANGED
@@ -15,3 +15,331 @@
15
15
 
16
16
 
17
17
  プロパティと同名の変数が出てきたりしてコードが非常に読みづらいのと、実際の保存処理のところが提示されていないのでなんとも言えないところではありますが。
18
+
19
+
20
+
21
+
22
+
23
+ ## 追記 Jul 16, 2020 11:00 AM
24
+
25
+ 「データの管理をする」と「データを画面に表示する」の2つの処理について、役割を分けたほうがよいです。
26
+
27
+ リスト表示画面 (NotesTableViewController) で生成した Note のインスタンスを詳細表示・編集画面 (DisplayNoteViewController) に渡したり、あるいは施した編集作業をリストに反映させるために詳細表示・編集画面からリスト表示画面に渡したり、というのはコードの見通しが良くないです。
28
+
29
+ 下記はシングルトンを使ってデータの管理をするクラス (StoredNotesManager) を実装する例です。実際に動かしてはいませんので適宜調整が必要だとは思いますが、参考になればと思います。
30
+
31
+
32
+
33
+ ```swift
34
+
35
+ class Note {
36
+
37
+ var title: String = ""
38
+
39
+ var content: String = ""
40
+
41
+ var memo1: String = ""
42
+
43
+ var memo2: String = ""
44
+
45
+ }
46
+
47
+
48
+
49
+ class StoredNotesManager {
50
+
51
+ static let shared = StoredNotesManager()
52
+
53
+ private var storedNotes: [Note] = []
54
+
55
+ private init() {
56
+
57
+ // FIXME: 永続化済みのデータがあればここで storedNotes に格納する
58
+
59
+ }
60
+
61
+
62
+
63
+ var count: Int {
64
+
65
+ get { return self.storedNotes.count }
66
+
67
+ }
68
+
69
+
70
+
71
+ func append(_ appendingNote: Note) -> Void {
72
+
73
+ self.storedNotes.append(appendingNote)
74
+
75
+ self.persistence()
76
+
77
+ }
78
+
79
+
80
+
81
+ func remove(at: Int) -> Void {
82
+
83
+ self.storedNotes.remove(at: at)
84
+
85
+ self.persistence()
86
+
87
+ }
88
+
89
+
90
+
91
+ func update(at: Int, newNote: Note) -> Void {
92
+
93
+ self.storedNotes[at] = newNote
94
+
95
+ self.persistence()
96
+
97
+ }
98
+
99
+
100
+
101
+ func get(at: Int) -> Note? {
102
+
103
+ if self.storedNotes.count <= at { return nil }
104
+
105
+ return self.storedNotes[at]
106
+
107
+ }
108
+
109
+
110
+
111
+ /// 永続化
112
+
113
+ private func persistence() {
114
+
115
+ // FIXME: 永続化処理を実装する
116
+
117
+ }
118
+
119
+ }
120
+
121
+ ```
122
+
123
+
124
+
125
+ ```swift
126
+
127
+ // MARK: - 永続化済みの Notes を一覧表示する
128
+
129
+ class NotesTableViewController: UITableViewController {
130
+
131
+ override func viewDidLoad() {
132
+
133
+ super.viewDidLoad()
134
+
135
+ }
136
+
137
+
138
+
139
+ // 表示すべきセルの数を返す
140
+
141
+ override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
142
+
143
+ return StoredNotesManager.shared.count
144
+
145
+ }
146
+
147
+
148
+
149
+ // テーブルの特定の行に対して、表示すべきcellを返す
150
+
151
+ // indexPathは、作成するcellがデーブルビュー内のどのセクションと行に属するかを示す
152
+
153
+ override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
154
+
155
+ //テーブルビューに表示される実際のcellをフェッチしている
156
+
157
+ //ダウンキャスト <- NotesTableViewCellがUITableViewCellのサブクラスであるため機能する
158
+
159
+ //コンパイラに具体的な種類のUITableViewCellを返すことを指示する
160
+
161
+ let cell = tableView.dequeueReusableCell(withIdentifier: "notesTableViewCell", for: indexPath) as! NotesTableViewCell
162
+
163
+
164
+
165
+ // indexPathは、cellForRowに渡された引数であり、テーブルビューがセルをどの行に表示するのかを示す
166
+
167
+ // indexPathのrowプロパティにアクセスし、検索する。
168
+
169
+ cell.noteTitleLabel.text = StoredNotesManager.shared.get(at: indexPath.row)?.title ?? ""
170
+
171
+
172
+
173
+ return cell
174
+
175
+ }
176
+
177
+
178
+
179
+ // commitEditingStyle : forRowAt indexPath: により、テーブルビューに追加の編集モードを有効にする
180
+
181
+ // cellを左スワイプした際に削除オプションが表示される
182
+
183
+ override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
184
+
185
+ // editingStyleが.deleteであるかどうかを調べる
186
+
187
+ if editingStyle == .delete {
188
+
189
+ // notesPathから渡されたindexPathのrowプロパティを使用して、選択されたノートをnotes配列から削除する
190
+
191
+ StoredNotesManager.shared.remove(at: indexPath.row)
192
+
193
+ }
194
+
195
+ }
196
+
197
+
198
+
199
+ override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
200
+
201
+ if let identifier = segue.identifier {
202
+
203
+ if identifier == "displayNote" {
204
+
205
+ print("Table view cell tapped")
206
+
207
+
208
+
209
+ // すべてのテーブルビューは、indexPathForSelecedRowというプロパティを持っている。
210
+
211
+ // ユーザーがテーブルビューからcellを選択した場合、特定のcellのindexPathにアクセス可能
212
+
213
+ // indexPathにはsection,rowのプロパティがあり、選択したテーブルビューのcellをマッピングする
214
+
215
+ // データモデル(ここではnotes配列)に関連付けることができる。
216
+
217
+ let indexPath = tableView.indexPathForSelectedRow!
218
+
219
+ (segue.destination as! DisplayNoteViewController).storedAt = indexPath.row
220
+
221
+ } else if identifier == "addNote" {
222
+
223
+ print("+ button tapped")
224
+
225
+ (segue.destination as! DisplayNoteViewController).isNewNote = true
226
+
227
+ }
228
+
229
+ }
230
+
231
+ }
232
+
233
+
234
+
235
+ @IBAction func unwindToNotesViewController(_ segue: UIStoryboardSegue) {
236
+
237
+
238
+
239
+ }
240
+
241
+ }
242
+
243
+
244
+
245
+ // MARK: - Note の詳細表示・編集
246
+
247
+ class DisplayNoteViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UITextFieldDelegate {
248
+
249
+ @IBOutlet weak var noteTitleTextField: UITextField!
250
+
251
+ @IBOutlet weak var noteContentxtFieTextView: UITextView!
252
+
253
+ @IBOutlet weak var memo1TextView: UITextView!
254
+
255
+ @IBOutlet weak var memo2TextView: UITextView!
256
+
257
+
258
+
259
+ var storedAt: Int = 0
260
+
261
+ var isNewNote: Bool = false
262
+
263
+
264
+
265
+ override func viewDidLoad() {
266
+
267
+ super.viewDidLoad()
268
+
269
+ }
270
+
271
+
272
+
273
+ override func viewWillAppear(_ animated: Bool){
274
+
275
+ super.viewWillAppear(animated)
276
+
277
+
278
+
279
+ // 新規作成の場合は空文字を入れる
280
+
281
+ if self.isNewNote {
282
+
283
+ self.noteTitleTextField.text = ""
284
+
285
+ noteContentxtFieTextView.text = ""
286
+
287
+ memo1TextView.text = ""
288
+
289
+ memo2TextView.text = ""
290
+
291
+ return
292
+
293
+ }
294
+
295
+
296
+
297
+ // 既存の Note の詳細表示・編集の場合は、永続化済みの Note から値を取得する
298
+
299
+ let note: Note? = StoredNotesManager.shared.get(at: self.storedAt)
300
+
301
+ self.noteTitleTextField.text = note?.title
302
+
303
+ self.noteContentxtFieTextView.text = note?.content
304
+
305
+ self.memo1TextView.text = note?.memo1
306
+
307
+ self.memo2TextView.text = note?.memo2
308
+
309
+ }
310
+
311
+
312
+
313
+ override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
314
+
315
+ if segue.identifier != "save" { return }
316
+
317
+ let newNote: Note = Note()
318
+
319
+ newNote.title = self.noteTitleTextField.text ?? ""
320
+
321
+ newNote.content = self.noteContentxtFieTextView.text
322
+
323
+ newNote.memo1 = self.memo1TextView.text
324
+
325
+ newNote.memo2 = self.memo2TextView.text
326
+
327
+
328
+
329
+ if isNewNote {
330
+
331
+ StoredNotesManager.shared.append(newNote)
332
+
333
+ return
334
+
335
+ }
336
+
337
+
338
+
339
+ StoredNotesManager.shared.update(at: self.storedAt, newNote: newNote)
340
+
341
+ }
342
+
343
+ }
344
+
345
+ ```