49108

[code]

    class ViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
    
    let imageView = UIImageView()
    let img = UIImage(named: "image")
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    
    
        imageView.image = img
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    override func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    
    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 3
    }
    
    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
    
        cell.contentView.addSubview(imageView)
    
        return cell
    }
    
[/code]

}

上のようにしても、コレクションビューに画像が表示されないのはなぜでしょうか。


CC BY-SA 4.0
2018-10-09T09:02:33.553
49101
2018-10-09T10:21:22.373
27271
question
swift ios xcode uicollectionview
UICollectionViewControllerのCellにUIImageViewが表示されない。


imageViewのインスタンスを使いまわしているためです。  
一つのViewは一つの親にしかもてないため、  
二つ目のセルが生成されて、addSubviewしたときに、一つ目のセルからはがされてしまします。  
三つ目のセルが生成されると、二つ目のセルからはがされて三つ目のセルに張り付きます。  
CollectionViewは前後のセルを内部的に生成しますので、画面外にあるセルに画像が張り付ていることになります。  
そのために、一見、一つも画像が張り付いていないように見えるのだと思います。

セルごとにimageViewのインスタンスを作成し、そこに画像をセットするようにしてみてください。

■追記  
セルごとに

[code]

    let imageView = UIImageView(image: UIImage(named: "image"))
    
[/code]

を追加してもダメであれば、以下を試して、各セルが赤くなるか確認してみてください。

[code]

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
    
        cell.backgroundColor = .red
    
        return cell
    }
    
[/code]


CC BY-SA 4.0
2018-10-09T09:26:35.007
49104
2018-10-09T10:17:49.660
2018-10-09T10:17:49.660
17014
17014
49101
answer


あなたのコードには複数の誤りがあります。

  * Viewは複数の場所を掛け持ちできない

user17014 さんの回答にも書かれている事柄です。

  * 詳細不詳のイニシャライザで`UIImageView`のインスタンスを作成している

`UIImageView`で引数のないイニシャライザの動作は不詳です。そのようなイニシャライザでインスンタンスを作成(`let imageView =
UIImageView()`のこと)しても、結果は保障されません。

  * `dequeueReusableCell(withReuseIdentifier:for:)`で取り出したセルに`addSubview(_:)`で子ビューを追加している

`dequeueReusableCell`で取得したセルは常に再利用品である可能性があります。従って、以前に追加した子ビューを削除することなく子ビューを追加すると、使っているうちにどんどん子ビューが増えていき、動作速度の上でもメモリ使用量の上でもシステムを圧迫することになります。

Storyboard上でPrototype Cellに子ビューを追加した上で、カスタムセルクラスを使用すれば、上記を全部いっぺんに解消できます。

* * *

### 以下のカスタムセルクラスを用意する。

MyCustomCell.swift (他の部分とつじつまを合わせてくれれば、クラス名は任意です。)

[code]

    import UIKit
    
    class MyCustomCell: UICollectionViewCell {
        @IBOutlet weak var imageView: UIImageView!
    
    }
    
[/code]

### Storyboard上の **Identifier** を`cell`としたプロトタイプセルで

  * **Custom Class** を`MyCustomCell`に変更する
  * `UIImageView`をレイアウトエディタ上で該当のプロトタイプセルに貼り付ける  
(必要に応じてConstraintを設定してください。)

  * 該当のプロトタイプセルを選択した状態でAssistantエディタを開き、レイアウトエディタ上の`UIImageView`を`MyCustomCell`クラスの`imageView`に接続する

### `ViewController`は以下のように修正

[code]

    import UIKit
    
    class ViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
    
        //画面に表示するviewは掛け持ちはできない
        //let imageView = UIImageView()
        let img = UIImage(named: "image")
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    
        override func numberOfSections(in collectionView: UICollectionView) -> Int {
            return 1
        }
    
        override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            return 3
        }
    
        override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            //次の行が実行時エラーになるならstoryboardでのcellの設定がうまくいっていない
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! MyCustomCell
    
            //`dequeueReusableCell(withReuseIdentifier:for:)`で取得したセルは常に再利用品である可能性がある
            //単純に取り出すたびにaddSubview()していくと、子ビューが増える一方でメモリ使用料・処理時間とも増え続ける
            cell.imageView.image = img
    
            return cell
        }
    }
    
[/code]

(`let cell = ...`の行は後ろの方に修正点があるのでご注意を。)

`UICollectionViewCell`のデフォルトは空っぽなので、storyboardを使用したくないと言う理由が特にあるのでない限り、storyboardでプロトタイプセルのレイアウトを行なって、カスタムセルクラスを使用することをお勧めします。


CC BY-SA 4.0
2018-10-09T10:21:22.373
49108
2018-10-09T10:21:22.373
13972
49101
answer