teratail header banner
teratail header banner
質問するログイン新規登録

質問編集履歴

2

ViewController(initialViewController)とNextViewcontrollerのコードを両方記載しました。また、実現したいことの項目等にも追記しています。

2021/02/16 15:22

投稿

zukaibito
zukaibito

スコア1

title CHANGED
File without changes
body CHANGED
@@ -1,94 +1,248 @@
1
1
  ### 前提・実現したいこと
2
2
 
3
- 構造体の配列をUserDefaults.standardに保存したのですが、保存したものを
3
+ NextViewControllerで構造体をUserDefaults.standardに保存したのですが、保存したものをViewControllerで利用したいです。
4
- TableViewCellに反映の方法が分からず困っています。
5
4
 
6
- 構造体にrateLabeltodonakamiを保存しており、
5
+ 構造体にtodo(Stringa型)rate(Int型)を保存しており、
7
- rateLabel==1の時に、heart1へtodonakamiを入れたいです。
6
+ をViewControllerへ渡して、TableViewのCellで利用したいです。
8
7
 
8
+ TODOリストにレーティング機能がついたようなアプリを作成しており、
9
- let heart1 = DoneStructList()と打つとnumberOfRowsInSectionと
9
+ rate == 1のときに、入力したテキスト(todo)をセクション1(heart1)へ反映させる
10
- cellForRowAtに下記ようなエラーメッージがでます。
10
+ rate == 1ときに、入力したテキスト(todo)をクション1(heart2)へ反映させる、といった形動かしたいと考えております。
11
11
 
12
12
 
13
+ ### やったこと
14
+ ViewControllerで利用しようとすると、エラーが出てしまいます。
15
+
16
+ let heart1 = UserDefaults.standard.data(forKey:"DoneStructList")!.filter {$0.rate==1
17
+ } 
13
- ### 発生してい問題・エラーメッセージ
18
+ **→ これを入れエラーが出てしまいます。**
14
19
 
15
- エラーメッセージ
16
- Value of type 'ViewController.DoneStructList' has no member 'count'
17
20
 
21
+ ### エラーコード
22
+ Value of type 'Data.Element' (aka 'UInt8') has no member 'rate'
23
+
18
24
  ### 該当のソースコード
19
25
  ```swift
26
+
20
- class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
27
+ struct DoneStructList: Codable {
21
28
 
22
- let heart1 = ["ご飯を食べる"]
29
+ var list = [DoneStruct]()
23
- let heart2 = ["夜更かし","ご飯を食べる"]
24
- let heart3 = ["片付けする","ご飯を食べる"]
25
- let heart4 = ["タバコを吸う","散歩する","サウナに行く","家で半身浴"]
26
- let heart5 = ["温泉に行く","服を買いに行く"]
27
- let sectionTitles = ["♡1","♡2","♡3","♡4","♡5"]
28
30
 
29
- @IBOutlet weak var tableView: UITableView!
31
+ struct DoneStruct: Codable{
32
+
33
+ var todo = String()
34
+ var rate = Int()
35
+
36
+ }
37
+ }
30
38
 
39
+
40
+ class NextViewController: UIViewController {
41
+
42
+
43
+ private var list: [DoneStructList.DoneStruct] = []
44
+
45
+ var rate = 0
46
+
47
+ @IBOutlet weak var TextField: UITextField!
48
+ @IBOutlet weak var Label: UILabel!
49
+ @IBOutlet weak var heart1: UIButton!
50
+ @IBOutlet weak var heart2: UIButton!
51
+ @IBOutlet weak var heart3: UIButton!
52
+ @IBOutlet weak var heart4: UIButton!
53
+ @IBOutlet weak var heart5: UIButton!
54
+
55
+ let heartFill = UIImage(named: "heart")
56
+ let heartEmpty = UIImage(named: "emptyheart")
57
+
31
58
  override func viewDidLoad() {
32
59
  super.viewDidLoad()
33
- // Do any additional setup after loading the view.
34
60
 
35
- tableView.delegate = self
61
+ list = getValue() ?? []
36
- tableView.dataSource = self
62
+
37
63
  }
64
+
38
65
 
39
- //Structの作成
40
- struct DoneStructList: Codable {
66
+ @IBAction func AddButton(_ sender: Any) {
41
67
 
68
+ //配列listの中にある構造体todo,rateそれぞれにTextField.textとrateを保存する。
69
+ let doneStruct = DoneStructList.DoneStruct(todo: TextField.text!,rate: rate)
42
- var list = [DoneStruct]()
70
+ list.append(doneStruct)
43
- struct DoneStruct: Codable{
44
-
45
- var todonakami = String()
46
- var rateLabel = Int()
71
+ save(list: list)
72
+
47
- }
73
+ dismiss(animated: true, completion: nil)
48
74
  }
49
-
50
-   var doneStructList = DoneStructList()
51
75
 
52
- //データ型にエンコード
76
+ //構造体を UserDefaultsへ保存するためにデータ型にエンコード
53
- private func serialize() -> Data?{
77
+ private func serialize(doneStructList:DoneStructList) -> Data?{
54
78
  do{
55
79
  let encoder = JSONEncoder()
56
- let data = try
80
+ return try
57
81
  encoder.encode(doneStructList)
58
- return data
59
- }catch{
82
+ }catch {
60
83
  return nil
61
84
  }
62
85
  }
63
-
86
+
64
87
  //データ型からデコード
65
- private func processJson(data: Data) -> [DoneStructList.DoneStruct]?{
88
+ private func processJson(data: Data) -> [DoneStructList.DoneStruct]? {
66
- do{
89
+ do {
67
90
  let jsonDecoder = JSONDecoder()
68
91
  let doneStructList = try
69
- jsonDecoder.decode(DoneStructList.self, from: data)
92
+ jsonDecoder.decode(DoneStructList.self,from: data)
70
93
  return doneStructList.list
71
- }catch{
94
+ }catch {
72
95
  return nil
73
96
  }
74
97
  }
75
-
98
+
76
-   //UserDefaultsに保存
99
+ //UserDefaultsに保存
77
- private func save(){
100
+ private func save(list: [DoneStructList.DoneStruct]){
101
+ let doneStructList = DoneStructList(list: list)
78
- guard let data = serialize() else
102
+ guard let data = serialize(doneStructList: doneStructList)else{
79
- { return }
103
+ return
104
+ }
80
105
  UserDefaults.standard.setValue(data, forKeyPath: "DoneStructList")
81
106
  }
82
107
 
83
108
  //UserDefaultsから取得
84
- func getValue() -> [DoneStructList.DoneStruct]?{
109
+ private func getValue() -> [DoneStructList.DoneStruct]? {
85
- guard let data = UserDefaults.standard.data(forKey: "DoneStructList") else
110
+ guard let data = UserDefaults.standard.data(forKey: "DoneStructList")else
86
- { return nil }
111
+ {return nil}
87
112
  return processJson(data: data)
88
113
  }
89
114
 
115
+ //以下ハートをタップしたら色が変わる、ラベルに数字が反映される。
116
+
90
- func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
117
+ @IBAction func heart1Tapped(_ sender: Any) {
91
118
 
119
+ switch rate {
120
+ case 1:
121
+ rate = 0
122
+
123
+ heart1.setImage(heartEmpty, for:UIControl.State() )
124
+ heart2.setImage(heartEmpty, for:UIControl.State() )
125
+ heart3.setImage(heartEmpty, for:UIControl.State() )
126
+ heart4.setImage(heartEmpty, for:UIControl.State() )
127
+ heart5.setImage(heartEmpty, for:UIControl.State() )
128
+
129
+
130
+ default:
131
+ rate = 1
132
+
133
+ heart1.setImage(heartFill, for:UIControl.State() )
134
+ heart2.setImage(heartEmpty, for:UIControl.State() )
135
+ heart3.setImage(heartEmpty, for:UIControl.State() )
136
+ heart4.setImage(heartEmpty, for:UIControl.State() )
137
+ heart5.setImage(heartEmpty, for:UIControl.State() )
138
+
139
+ }
140
+
141
+ Label.text = String(rate)
142
+ }
143
+
144
+ @IBAction func heart2Tapped(_ sender: Any) {
145
+
146
+ //ボタンをタップした時の動作
147
+ rate = 2
148
+
149
+ heart1.setImage(heartFill, for:UIControl.State() )
150
+ heart2.setImage(heartFill, for:UIControl.State() )
151
+ heart3.setImage(heartEmpty, for:UIControl.State() )
152
+ heart4.setImage(heartEmpty, for:UIControl.State() )
153
+ heart5.setImage(heartEmpty, for:UIControl.State() )
154
+
155
+ Label.text = String(rate)
156
+
157
+ }
158
+
159
+ @IBAction func heart3Tapped(_ sender: Any) {
160
+
161
+ rate = 3
162
+
163
+ heart1.setImage(heartFill, for:UIControl.State() )
164
+ heart2.setImage(heartFill, for:UIControl.State() )
165
+ heart3.setImage(heartFill, for:UIControl.State() )
166
+ heart4.setImage(heartEmpty, for:UIControl.State() )
167
+ heart5.setImage(heartEmpty, for:UIControl.State() )
168
+
169
+ Label.text = String(rate)
170
+
171
+ }
172
+
173
+ @IBAction func heart4Tapped(_ sender: Any) {
174
+
175
+ rate = 4
176
+
177
+ heart1.setImage(heartFill, for:UIControl.State() )
178
+ heart2.setImage(heartFill, for:UIControl.State() )
179
+ heart3.setImage(heartFill, for:UIControl.State() )
180
+ heart4.setImage(heartFill, for:UIControl.State() )
181
+ heart5.setImage(heartEmpty, for:UIControl.State() )
182
+
183
+ Label.text = String(rate)
184
+
185
+ }
186
+
187
+
188
+ @IBAction func heart5Tapped(_ sender: Any) {
189
+
190
+ rate = 5
191
+
192
+ heart1.setImage(heartFill, for:UIControl.State() )
193
+ heart2.setImage(heartFill, for:UIControl.State() )
194
+ heart3.setImage(heartFill, for:UIControl.State() )
195
+ heart4.setImage(heartFill, for:UIControl.State() )
196
+ heart5.setImage(heartFill, for:UIControl.State() )
197
+
198
+ Label.text = String(rate)
199
+
200
+ }
201
+ ```
202
+
203
+
204
+
205
+
206
+ ```
207
+
208
+ //NextViewControllerで保存した値を以下のViewControllerで使用したい。
209
+
210
+ class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
211
+
212
+   //いったん文字を入れておく。ここにNextViewControllerで保存したtodoを反映させたい。rate==1のときに入力したテキスト(todo)をheart1へ入れる、rate==2のときに入力したテキスト(todo)をheart2へ入れるという形でいれたい。
213
+ let heart1 = ["ご飯を食べる"]
214
+ let heart2 = ["夜更かし","ご飯を食べる"]
215
+ let heart3 = ["片付けする","ご飯を食べる"]
216
+ let heart4 = ["タバコを吸う","散歩する","サウナに行く","家で半身浴"]
217
+ let heart5 = ["温泉に行く","服を買いに行く"]
218
+
219
+ let sectionTitles = ["♡1","♡2","♡3","♡4","♡5"]
220
+
221
+
222
+ @IBOutlet weak var tableView: UITableView!
223
+
224
+
225
+ override func viewDidLoad() {
226
+ super.viewDidLoad()
227
+ // Do any additional setup after loading the view.
228
+
229
+
230
+ tableView.delegate = self
231
+ tableView.dataSource = self
232
+ }
233
+
234
+ //5つのセクションを用意する
235
+ func numberOfSections(in tableView: UITableView) -> Int {
236
+ return 5
237
+ }
238
+
239
+   //sectionTitlesの数だけセクションを用意する
240
+ func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
241
+ return sectionTitles[section]
242
+ }
243
+
244
+ func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
245
+
92
246
  if section == 0{
93
247
  return heart1.count
94
248
  }else if section == 1{
@@ -101,46 +255,60 @@
101
255
  return heart5.count
102
256
  }else{
103
257
  return 0
104
- }
258
+ }
105
259
  }
106
260
 
107
261
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
108
262
 
109
- let cell = tableView.dequeueReusableCell(withIdentifier: "cell",for: indexPath)
263
+ let cell = tableView.dequeueReusableCell(withIdentifier: "Cell",for: indexPath)
110
-
264
+
265
+
111
- if indexPath.section == 0 {
266
+ if indexPath.section == 0 {
112
- cell.textLabel?.text = heart1[indexPath.row]
267
+ cell.textLabel?.text =heart1[indexPath.row]
268
+
113
- }else if indexPath.section == 1{
269
+ }else if indexPath.section == 1{
114
270
  cell.textLabel?.text = heart2[indexPath.row]
271
+
115
- }else if indexPath.section == 2{
272
+ }else if indexPath.section == 2{
116
273
  cell.textLabel?.text = heart3[indexPath.row]
274
+
117
- }else if indexPath.section == 3{
275
+ }else if indexPath.section == 3{
118
276
  cell.textLabel?.text = heart4[indexPath.row]
277
+
119
- }else if indexPath.section == 4{
278
+ }else if indexPath.section == 4{
120
279
  cell.textLabel?.text = heart5[indexPath.row]
121
- }
280
+ }
281
+
122
- return cell
282
+ return cell
283
+
123
284
  }
285
+
286
+ @IBAction func AddButton(_ sender: Any) {
287
+
288
+ performSegue(withIdentifier: "next", sender: nil)
289
+
290
+ }
291
+
292
+ }
124
293
  ```
125
294
 
126
-
127
295
 
128
296
 
129
297
  ### 試したこと
298
+
130
- let heart1 = DoneStructList() → このように入れるとエラーがでます。
299
+ let heart1 = UserDefaults.standard.data(forKey:"DoneStructList")!.filter {$0.rate==1
300
+ } 
301
+ **→ これを入れるとエラーが出てしまいます。**
131
- **→rateLabelが1のtodonakamiを入れたい**
302
+ **→rate==1のとき入力したテキスト(todo)heart1へ入れたい**
132
303
  let heart2 = ["夜更かし","ご飯を食べる"]
133
- **→rateLabelが2のtodonakamiを入れたい**
304
+ **→rate==2のとき入力したテキスト(todo)heart2へ入れたい**
134
305
  let heart3 = ["片付けする","ご飯を食べる"]
135
- ** →rateLabelが3のtodonakamiを入れたい**
306
+ ** →rate==3のとき入力したテキスト(todo)heart3へ入れたい**
136
307
  let heart4 = ["タバコを吸う","散歩する","サウナに行く","家で半身浴"]
137
- **→rateLabelが4のtodonakamiを入れたい**
308
+ **→rrate==4のとき入力したテキスト(todo)heart4へ入れたい**
138
309
  let heart5 = ["温泉に行く","服を買いに行く"]
139
- **→rateLabelが5のtodonakamiを入れたい**
310
+ **→rate==5のとき入力したテキスト(todo)heart5へ入れたい**
140
311
 
141
312
 
142
- heart1~5に保存したStructを使いたいのですが、どのように実装すれば
313
+ NextViewControllerで保存したStructをViewControllerで使いたいのですが、
143
- いいでしょうか。
314
+ どのように実装すればいいでしょうか。
144
- rateLabel==1の時に、heart1へtodonakamiを,
145
- rateLabel==2の時に、heart2へtodonakamiを,
146
- というような形で入れたいです。

1

UserDefaultsへ保存するコードを記載

2021/02/16 15:22

投稿

zukaibito
zukaibito

スコア1

title CHANGED
File without changes
body CHANGED
@@ -47,6 +47,20 @@
47
47
  }
48
48
  }
49
49
 
50
+   var doneStructList = DoneStructList()
51
+
52
+ //データ型にエンコード
53
+ private func serialize() -> Data?{
54
+ do{
55
+ let encoder = JSONEncoder()
56
+ let data = try
57
+ encoder.encode(doneStructList)
58
+ return data
59
+ }catch{
60
+ return nil
61
+ }
62
+ }
63
+
50
64
  //データ型からデコード
51
65
  private func processJson(data: Data) -> [DoneStructList.DoneStruct]?{
52
66
  do{
@@ -58,6 +72,13 @@
58
72
  return nil
59
73
  }
60
74
  }
75
+
76
+   //UserDefaultsに保存
77
+ private func save(){
78
+ guard let data = serialize() else
79
+ { return }
80
+ UserDefaults.standard.setValue(data, forKeyPath: "DoneStructList")
81
+ }
61
82
 
62
83
  //UserDefaultsから取得
63
84
  func getValue() -> [DoneStructList.DoneStruct]?{