Search code examples
iosiphoneswiftuiimageview

UIImageView within UICollectionVIew appears nil


I'm trying to put images(appr. 100+) into UIImageView within UICollectionViewCell. Since that's quite amount, I tried to make a plist file that contains names of the file and retrieve names from it.

itemCollectionViewController

//
//  itemCollectionViewController.swift
//  phdrink
//
//  Created by Canor on 2017. 3. 3..
//  Copyright © 2017년 Scarlett Systems. All rights reserved.
//

import UIKit

let reuseIdentifier = "itemCell"
let screenRect: CGRect = UIScreen.main.bounds
let screenSizeWidth = screenRect.width

var gameDataIcons : [String] = [] // gameDataIcons is Array

class itemCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Uncomment the following line to preserve selection between presentations
        // self.clearsSelectionOnViewWillAppear = false

        // Register cell classes
        self.collectionView!.register(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)


        // Do any additional setup after loading the view.
        initGameDataIcon()
        gameCollectionViewCell().setGameDataIcon()
        collectionView?.reloadData()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using [segue destinationViewController].
        // Pass the selected object to the new view controller.
    }
    */

    // MARK: UICollectionViewDataSource

    override func numberOfSections(in collectionView: UICollectionView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }

    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of items
        return 99
    }


    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath)

        // Configure the cell
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

        print(screenSizeWidth / 3.0)
        return CGSize(width: (screenSizeWidth - 80.0) / 2.0 , height: (screenSizeWidth - 80.0) / 2.0)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat
    {

        return 20;
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {

        return 5;
    }

    func initGameDataIcon(){
        let inputFile = Bundle.main.path(forResource: "gamedata", ofType: "plist")
        let inputDataArray = NSArray(contentsOfFile: inputFile!)
        for inputItem in inputDataArray as! [Dictionary<String,String>]{
            let gameDataIcon = inputItem["img_filename"]
            gameDataIcons.append(gameDataIcon!)
        }
    }
}

gameDataIcon.swift

//
//  gameDataIcon.swift
//  phdrink
//
//  Created by Canor on 2017. 3. 4..
//  Copyright © 2017년 Scarlett Systems. All rights reserved.
//

import Foundation

class GameDataIcon{

    var value_img_filename: String

    init(dataDictionary:Dictionary<String,String>){
        value_img_filename = dataDictionary["img_filename"]!
    }
}

gameCollectionViewCell

//
//  gameCollectionViewCell.swift
//  phdrink
//
//  Created by Canor on 2017. 3. 4..
//  Copyright © 2017년 Scarlett Systems. All rights reserved.
//

import UIKit

class gameCollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var gameIcon: UIImageView!

    func setGameDataIcon(){
        for singlegameicon in gameDataIcons {
            print(singlegameicon)
            gameIcon.image = UIImage(named: singlegameicon)
        }
    }
}

but when I run this code from Simulator, xCode throws EXC_BAD_INSTRUCTION error saying gameIcon, that is UIImageView, is nil, which shouldn't be. I thought I was doing something incorrect with UIImage(named: part, but it wasn't. Other than that, I don't get where this error comes from. Any suggestions would be appreciated.

  • images assets are placed in Assets.xcassets correctly, I hope.
  • name in the plist matches name of the file.
  • gameDataIcons array does have array of names of file.
  • gameIcon is connected to UIImageView properly.

I'm totally new to swift, so please forgive me if this question is a basic one. Thanks.


Solution

  • I suggest reading the documentation of UICollectionView first. It seems you don't understand how it is supposed to work.

    In short, you can only assign one UIImage to an UIImageView. But in method setGameDataIcon you try to assign all images to one image view in a loop.

    You could add a parameter to setGameDataIcon which is the index of the image that should be assigned to the image view of that particular cell. Second you need to move gameCollectionViewCell().setGameDataIcon() from viewDidLoad() to collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) using indexPath.row as parameter for setGameDataIcon().