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

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回答

2855閲覧

[Swift] CollectionViewの複数のセル内容を表示させる方法

s1209

総合スコア13

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クリップ

投稿2018/05/08 09:54

編集2018/05/08 09:54

CollectionViewのセルに編集画面で入力した値を表示させ続けたいのですが、ある1つのセルに表示させたあと違うセルに表示させると、前に表示させたセルの内容が消えてしまいます。

流れとしては、ViewControllerのCollectionViewのセルをタップ→編集画面に遷移→TextFieldに表示させたい値を入力→完了ボタンを押すと画面がViewControllerに戻り、タップしたセルのみに値が表示される。
タップしたセルの番号(cellNumber)とindexPath.rowが一致した時に値を表示させています。

値を表示させることはできるのですが、常に1つのセルしか表示させられません。

cellForRowAtの中身が間違ってるのでしょうか?

<該当コード(一部省略)>

Swift

1import UIKit 2 3class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { 4 5 static var cellNumber: Int = 0 6 @IBOutlet weak var collectionView: UICollectionView! 7 8 static var testArray: [Class] = [] 9 10 override func viewDidLoad() { 11 super.viewDidLoad() 12 13 collectionView.delegate = self 14 collectionView.dataSource = self 15 16 collectionView.register(UINib(nibName: "CollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "CollectionViewCell") 17 18 } 19 20 21 override func viewWillAppear(_ animated: Bool) { 22 23// 取得 24 if let data = UserDefaults.standard.object(forKey: "TimeTable") as? Data, let array = NSKeyedUnarchiver.unarchiveObject(with: data) as? [Class] { 25 print("取得:(array)") 26 } else { 27 print("Error") 28 } 29 30 collectionView.reloadData() 31 } 32 33 34// セルが選択された時 35 func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 36 37 ViewController.cellNumber = indexPath.row 38 39 if ViewController.cellNumber == indexPath.row { 40 print("セル番号:(indexPath.row)") 41 } 42 43 performSegue(withIdentifier: "Modal1", sender: self) 44 } 45 46 47// セルの内容 48 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 49 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell 50 cell.backgroundColor = UIColor.groupTableViewBackground 51 52 for data in ViewController.testArray { 53 if indexPath.row == data.cellNumber { 54 cell.classLabel.text = data.className 55 cell.roomLabel.text = data.roomName 56 } else { 57 cell.classLabel.text = "" 58 cell.roomLabel.text = "" 59 } 60 } 61 return cell 62 }

Swift

1import UIKit 2 3class Class: NSObject, NSCoding { 4 5 6 let className: String 7 let roomName: String 8 let cellNumber: Int 9 10 init(className: String, roomName: String, cellNumber: Int) { 11 12 self.className = className 13 self.roomName = roomName 14 self.cellNumber = cellNumber 15 } 16 17 func encode(with aCoder: NSCoder) { 18 aCoder.encode(self.className, forKey: "name") 19 aCoder.encode(self.roomName, forKey: "room") 20 aCoder.encode(self.cellNumber, forKey: "number") 21 } 22 23 required init?(coder aDecoder: NSCoder) { 24 self.className = aDecoder.decodeObject(forKey: "name") as! String 25 self.roomName = aDecoder.decodeObject(forKey: "room") as! String 26 self.cellNumber = aDecoder.decodeInteger(forKey: "number") 27 } 28} 29 30class Edit: UIViewController { 31 32 @IBOutlet weak var classTextField: UITextField! 33 @IBOutlet weak var roomTextField: UITextField! 34 35 override func viewDidLoad() { 36 super.viewDidLoad() 37 38 } 39 40 41// 完了ボタンを押した時 42 @IBAction func tappedButton(_ sender: UIButton) { 43 44 let classData = Class(className:classTextField.text!, roomName: roomTextField.text!, cellNumber: ViewController.cellNumber) 45 ViewController.testArray.append(classData) 46 47// 保存 48 UserDefaults.standard.set(NSKeyedArchiver.archivedData(withRootObject: ViewController.testArray), forKey: "TimeTable") 49 UserDefaults.standard.synchronize() 50 51 print("配列の中身:(ViewController.testArray)") 52 print("保存:(UserDefaults.standard.set(NSKeyedArchiver.archivedData(withRootObject: ViewController.testArray), forKey: "TimeTable"))") 53 54 dismiss(animated: true) {} 55 }

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

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

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

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

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

guest

回答1

0

ベストアンサー

下記の箇所でcellに空文字を設定しているからではないでしょうか?

if indexPath.row == data.cellNumber { cell.classLabel.text = data.className cell.roomLabel.text = data.roomName } else { // ↓空文字を設定 cell.classLabel.text = "" cell.roomLabel.text = "" }
for data in ViewController.testArray { if indexPath.row == data.cellNumber { cell.classLabel.text = data.className cell.roomLabel.text = data.roomName } }

[追記]

if let data = ViewController.testArray.first(where: { $0.cellNumber == indexPath.row }) { cell.roomLabel.text = data.roomName cell.classLabel.text = data.className } else { cell.classLabel.text = "" cell.roomLabel.text = "" }

投稿2018/05/08 21:38

編集2018/05/09 11:52
newmt

総合スコア1277

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

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

s1209

2018/05/09 07:27

ありがとうございます。 空文字部分を消したらセルに値を表示させ続けることができました! しかし、表示させるセルを増やすと、以前に表示させていたセルの値が指定していないセルに複製されて表示されてしまいます。 このような場合はreloadDataの書き方が悪いのでしょうか?
newmt

2018/05/09 09:37

全体像がわからないので可能性でしか言えないのですが、カスタムセル側に設定した値を保持するとどうなりますでしょうか? let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell はセルを再利用するという意味で、以前表示されていたセルを使用します。
s1209

2018/05/09 09:58

カスタムセルには、ドラッグ&ドロップでラベルを配置しているだけでコードを書いたり値を設定したりなどはしていません…。 セルの再利用が原因の可能性もあるのでしょうか…
newmt

2018/05/09 10:18

セルを再利用しているので、以前使用していた値が表示されているのかと思いました。セルに値を取得する部分を追記したコードに変えるとどうなりますでしょうか?
s1209

2018/05/09 11:23

ありがとうございます! コードを変えてみたら複製されなくなりましたが、1つのセル内に表示させたい値が2種類あり、追記コードだと1つの値は複製されずもう1つの値は複製される、という表示になってしまいました。。。 このような場合はどこを書き換えればいいでしょうか?
newmt

2018/05/09 11:52

間違いがあったので修正しました。同じ変数に空文字設定していました。。。
s1209

2018/05/09 12:30

私も間違いに気づきませんでした… 修正後、希望通りに表示させることができました。 しばらく悩んでいたところなので解決できて本当に嬉しいです。 ちなみに、first(where:)のコードは初見なので調べてみたのですが、配列の最初の要素を取り出す?という解釈で合ってますでしょうか?
s1209

2018/05/09 23:18

ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問