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

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

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

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

Q&A

解決済

1回答

826閲覧

CollectionViewのdataSourceメソッドが発火しない

HiakruKuroda

総合スコア13

Swift

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

0グッド

0クリップ

投稿2020/09/29 05:07

UICollectionViewのdataSourceメソッドが発火しません。
storyboardは使っておらず、コードのみの実装です。

ViewController

1class ViewController: UIViewController { 2 3 private var contentCollectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewLayout()) 4 5 override func viewDidLoad() { 6 super.viewDidLoad() 7 8 contentCollectionView.dataSource = self 9 contentCollectionView.register(ContentCollectionViewCell.self, forCellWithReuseIdentifier: "Cell") 10 11 let layout = UICollectionViewFlowLayout() 12 layout.itemSize = CGSize(width: screenWidth * 0.4, height: 60) 13 contentCollectionView = UICollectionView(frame: .zero, collectionViewLayout: layout) 14 15 contentCollectionView.backgroundColor = .yellow 16 self.view.addSubview(contentCollectionView) 17 contentCollectionView.translatesAutoresizingMaskIntoConstraints = false 18 contentCollectionView.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true 19 contentCollectionView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true 20 contentCollectionView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true 21 contentCollectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0).isActive = true 22 } 23} 24 25extension ViewController: UICollectionViewDataSource { 26 func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 27 return 6 28 } 29 30 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 31 print("dataSorce method") 32 let cell = contentCollectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) 33 return cell 34 } 35}

ContentCollectionViewCell

1class ContentCollectionViewCell: UICollectionViewCell { 2 3 let titleLabel = UILabel() 4 let numberLabel = UILabel() 5 6 override func awakeFromNib() { 7 super.awakeFromNib() 8 } 9 10 override init(frame: CGRect) { 11 super.init(frame: frame) 12 print("cell init") 13 14 setupView() 15 } 16 17 required init?(coder: NSCoder) { 18 fatalError("init(coder:) has not been implemented") 19 } 20 21 func setupView() { 22 titleLabel.text = "default" 23 self.contentView.addSubview(titleLabel) 24 titleLabel.translatesAutoresizingMaskIntoConstraints = false 25 titleLabel.centerXAnchor.constraint(equalTo: self.contentView.centerXAnchor, constant: 0).isActive = true 26 titleLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 10).isActive = true 27 28 numberLabel.text = "default" 29 self.contentView.addSubview(numberLabel) 30 numberLabel.translatesAutoresizingMaskIntoConstraints = false 31 numberLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 3).isActive = true 32 numberLabel.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 0).isActive = true 33 } 34}

・cellForItemAt内のprintと、カスタムセルのinit内のprintは実行されていない。
・dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)の
identifierを登録していない適当な文字列に変更してもエラーがおきない。

どこか見落としている箇所はありますか?

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

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

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

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

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

guest

回答1

0

ベストアンサー

現在のコードだと

Swift

1class ViewController: UIViewController { 2 3 private var contentCollectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewLayout())

上記の部分で UICollactionView のインスタンスを作成し、viewDidLoad()

Swift

1 override func viewDidLoad() { 2 super.viewDidLoad() 3 4 contentCollectionView.dataSource = self 5 contentCollectionView.register(ContentCollectionViewCell.self, forCellWithReuseIdentifier: "Cell") 6 7 let layout = UICollectionViewFlowLayout() 8 layout.itemSize = CGSize(width: screenWidth * 0.4, height: 60)

Cell の登録や Cell のサイズを設定したあと、

Swift

1 contentCollectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)

再度 UICollectionView のインスタンスを作り直しているため、dataSourceregister(_:forCellWithReuseIdentifier:) の情報がリセットされてしまっていることが原因かと思います。

対策は色々あるかと思いますが、ひとつはクロージャと lazy キーワードを使い、

Swift

1class ViewController: UIViewController { 2 private lazy var contentCollectionView: UICollectionView = { 3 var layout = UICollectionViewFlowLayout() 4 layout.itemSize = CGSize(width: self.view.frame.width * 0.4, height: 60) 5 return UICollectionView(frame: .zero, collectionViewLayout: layout) 6 }() 7 8 override func viewDidLoad() { 9 super.viewDidLoad() 10 11 contentCollectionView.dataSource = self 12 contentCollectionView.register(ContentCollectionViewCell.self, forCellWithReuseIdentifier: "Cell")

のような感じにする方法があるかと思います。

あるいは、とりあえず適当な引数を与えて一度インスタンスを作り、その後順番を追って上書きする方法もあります

Swift

1class ViewController: UIViewController { 2 private var contentCollectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewLayout()) 3 4 override func viewDidLoad() { 5 super.viewDidLoad() 6 7 let layout = UICollectionViewFlowLayout() 8 layout.itemSize = CGSize(width: self.view.frame.width * 0.4, height: 60) 9 contentCollectionView = UICollectionView(frame: .zero, collectionViewLayout: layout) 10 11 contentCollectionView.dataSource = self 12 contentCollectionView.register(ContentCollectionViewCell.self, forCellWithReuseIdentifier: "Cell")

残りの手段としては、contentCollectionView をオプショナル型で宣言する方法もありますが、それなりに危険性がありますので、その内容を把握されて使うのがよろしいかと思います。

Swift

1 private var contentCollectionView:UICollectionView! 2 3 override func viewDidLoad() { 4 super.viewDidLoad() 5 6 let layout = UICollectionViewFlowLayout() 7 layout.itemSize = CGSize(width: self.view.frame.width * 0.4, height: 60) 8 contentCollectionView = UICollectionView(frame: .zero, collectionViewLayout: layout) 9 10 contentCollectionView.dataSource = self 11 contentCollectionView.register(ContentCollectionViewCell.self, forCellWithReuseIdentifier: "Cell")

投稿2020/09/29 06:16

TsukubaDepot

総合スコア5086

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

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

HiakruKuroda

2020/09/29 06:29

なるほど!質問のコードで上書きできていると勘違いしていました。 無事実装できました。 回答ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問