How to create UICollectionViewCell programmatically

s_s picture s_s · Sep 11, 2016 · Viewed 72.3k times · Source

I'm trying to create UICollectionView programatically. I need to add labels inside the cells, so I Created CollectionViewCell class.

This is the class:

import UIKit

class MyCollectionViewCell: UICollectionViewCell {

    override init(frame: CGRect) {
        super.init(frame: frame)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

And this is the collectionView implementation class:

import UIKit

class TwoViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, UICollectionViewDelegate {

    let leftAndRightPaddings: CGFloat = 80.0
    let numberOfItemsPerRow: CGFloat = 7.0
    let screenSize: CGRect = UIScreen.main.bounds
    private let cellReuseIdentifier = "collectionCell"
    var items = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31"]

    override func viewDidLoad() {
        super.viewDidLoad()
        let flowLayout = UICollectionViewFlowLayout()
        let collectionView = UICollectionView(frame: self.view.bounds, collectionViewLayout: flowLayout)
        collectionView.register(MyCollectionViewCell.self, forCellWithReuseIdentifier: cellReuseIdentifier)

        collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "collectionCell")
        collectionView.delegate = self
        collectionView.dataSource = self
        collectionView.backgroundColor = UIColor.cyan

        self.view.addSubview(collectionView)
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
    {
        return self.items.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
    {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellReuseIdentifier, for: indexPath) as! MyCollectionViewCell
        cell.backgroundColor = UIColor.green
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
    {
        let width = (screenSize.width-leftAndRightPaddings)/numberOfItemsPerRow
        return CGSize(width: width, height: width)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets
    {
        return UIEdgeInsets(top: 20, left: 8, bottom: 5, right: 8)
    }        
}

The error happens when the cell produced:

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
{
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier(cellReuseIdentifier, forIndexPath: indexPath) as! MyCollectionViewCell

The error is:

Could not cast value of type 'UICollectionViewCell' (0x1033cc820) to 'CollectionViewProgramatically.MyCollectionViewCell' (0x1015a4f88).

Answer

Bob Lee picture Bob Lee · Sep 11, 2016

Try to copy and paste this code into your xcode, it should work

//
//  HomeVIewController.swift
//  Photolancer
//
//  Created by Lee SangJoon  on 9/8/16.
//  Copyright © 2016 Givnite. All rights reserved.
//

import UIKit


class HomeViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {



    var collectionview: UICollectionView!
    var cellId = "Cell"

    override func viewDidLoad() {
        super.viewDidLoad()

        // Create an instance of UICollectionViewFlowLayout since you cant
        // Initialize UICollectionView without a layout
        let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
        layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
        layout.itemSize = CGSize(width: view.frame.width, height: 700)

        collectionview = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
        collectionview.dataSource = self
        collectionview.delegate = self
        collectionview.registerClass(FreelancerCell.self, forCellWithReuseIdentifier: cellId)
        collectionview.showsVerticalScrollIndicator = false
        collectionview.backgroundColor = UIColor.whiteColor()
        self.view.addSubview(collectionview)

    }

    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 10
    }


    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionview.dequeueReusableCellWithReuseIdentifier(cellId, forIndexPath: indexPath) as! FreelancerCell
        return cell
    }


}








class FreelancerCell: UICollectionViewCell {


    let profileImageButton: UIButton = {
        let button = UIButton()
        button.backgroundColor = UIColor.whiteColor()
        button.layer.cornerRadius = 18
        button.clipsToBounds = true
        button.setImage(UIImage(named: "Profile"), forState: .Normal)

        button.translatesAutoresizingMaskIntoConstraints = false
        return button
    }()


    let nameLabel: UILabel = {
        let label = UILabel()
        label.font = UIFont.systemFontOfSize(14)
        label.textColor = UIColor.darkGrayColor()
        label.text = "Bob Lee"
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()


    let distanceLabel: UILabel = {
        let label = UILabel()
        label.textColor = UIColor.lightGrayColor()
        label.font = UIFont.systemFontOfSize(14)
        label.text = "30000 miles"
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()

    let pricePerHourLabel: UILabel = {
        let label = UILabel()
        label.textColor = UIColor.darkGrayColor()
        label.font = UIFont.systemFontOfSize(14)
        label.text = "$40/hour"
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()



    let ratingLabel: UILabel = {
        let label = UILabel()
        label.textColor = UIColor.lightGrayColor()
        label.font = UIFont.systemFontOfSize(14)
        label.text = "4.9+"
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()


    let showCaseImageView: UIImageView = {
        let imageView = UIImageView()
        imageView.backgroundColor = UIColor.whiteColor()
        imageView.image = UIImage(named: "Profile")
        imageView.translatesAutoresizingMaskIntoConstraints = false
        return imageView
    }()


    let likesLabel: UILabel = {
        let label = UILabel()
        label.textColor = UIColor.lightGrayColor()
        label.font = UIFont.systemFontOfSize(14)
        label.text = "424 likes"
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()


    let topSeparatorView: UIView = {
        let view = UIView()
        view.backgroundColor = UIColor.darkGrayColor()
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()

    let bottomSeparatorView: UIView = {
        let view = UIView()
        view.backgroundColor = UIColor.darkGrayColor()
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()


    let likeButton: UIButton = {
        let button = UIButton()
        button.setTitle("Like", forState: .Normal)
        button.titleLabel?.font = UIFont.systemFontOfSize(18)
        button.setTitleColor(UIColor.darkGrayColor(), forState: .Normal)
        button.translatesAutoresizingMaskIntoConstraints = false
        return button
    }()

    let hireButton: UIButton = {
        let button = UIButton()
        button.setTitle("Hire", forState: .Normal)
        button.titleLabel?.font = UIFont.systemFontOfSize(18)
        button.setTitleColor(UIColor.darkGrayColor(), forState: .Normal)
        button.translatesAutoresizingMaskIntoConstraints = false
        return button
    }()


    let messageButton: UIButton = {
        let button = UIButton()
        button.setTitle("Message", forState: .Normal)
        button.titleLabel?.font = UIFont.systemFontOfSize(18)
        button.setTitleColor(UIColor.darkGrayColor(), forState: .Normal)
        button.translatesAutoresizingMaskIntoConstraints = false
        return button
    }()



    let stackView: UIStackView = {
        let sv = UIStackView()
        sv.axis  = UILayoutConstraintAxis.Horizontal
        sv.alignment = UIStackViewAlignment.Center
        sv.distribution = UIStackViewDistribution.FillEqually
        sv.translatesAutoresizingMaskIntoConstraints = false;
        return sv
    }()




    override init(frame: CGRect) {
        super.init(frame: frame)

        addViews()
    }




    func addViews(){
        backgroundColor = UIColor.blackColor()

        addSubview(profileImageButton)
        addSubview(nameLabel)
        addSubview(distanceLabel)
        addSubview(pricePerHourLabel)
        addSubview(ratingLabel)
        addSubview(showCaseImageView)
        addSubview(likesLabel)

        addSubview(topSeparatorView)
        addSubview(bottomSeparatorView)

        // Stack View
        addSubview(likeButton)
        addSubview(messageButton)
        addSubview(hireButton)
        addSubview(stackView)


        profileImageButton.leftAnchor.constraintEqualToAnchor(leftAnchor, constant: 5).active = true
        profileImageButton.topAnchor.constraintEqualToAnchor(topAnchor, constant: 10).active = true
        profileImageButton.heightAnchor.constraintEqualToConstant(36).active = true
        profileImageButton.widthAnchor.constraintEqualToConstant(36).active = true

        nameLabel.leftAnchor.constraintEqualToAnchor(profileImageButton.rightAnchor, constant: 5).active = true
        nameLabel.centerYAnchor.constraintEqualToAnchor(profileImageButton.centerYAnchor, constant: -8).active = true
        nameLabel.rightAnchor.constraintEqualToAnchor(pricePerHourLabel.leftAnchor).active = true

        distanceLabel.leftAnchor.constraintEqualToAnchor(nameLabel.leftAnchor).active = true
        distanceLabel.centerYAnchor.constraintEqualToAnchor(profileImageButton.centerYAnchor, constant: 8).active = true
        distanceLabel.widthAnchor.constraintEqualToConstant(300)

        pricePerHourLabel.rightAnchor.constraintEqualToAnchor(rightAnchor, constant: -10).active = true
        pricePerHourLabel.centerYAnchor.constraintEqualToAnchor(nameLabel.centerYAnchor).active = true

        // Distance depeneded on the priceLabel and distance Label
        ratingLabel.rightAnchor.constraintEqualToAnchor(pricePerHourLabel.rightAnchor).active = true
        ratingLabel.centerYAnchor.constraintEqualToAnchor(distanceLabel.centerYAnchor).active = true

        showCaseImageView.topAnchor.constraintEqualToAnchor(profileImageButton.bottomAnchor, constant: 10).active = true
        showCaseImageView.widthAnchor.constraintEqualToAnchor(widthAnchor).active = true
        showCaseImageView.heightAnchor.constraintEqualToConstant(UIScreen.mainScreen().bounds.width - 20).active = true

        likesLabel.topAnchor.constraintEqualToAnchor(showCaseImageView.bottomAnchor, constant: 10).active = true
        likesLabel.leftAnchor.constraintEqualToAnchor(profileImageButton.leftAnchor).active = true

        topSeparatorView.topAnchor.constraintEqualToAnchor(likesLabel.bottomAnchor, constant: 10).active = true
        topSeparatorView.widthAnchor.constraintEqualToAnchor(widthAnchor).active = true
        topSeparatorView.heightAnchor.constraintEqualToConstant(0.5).active = true

        stackView.addArrangedSubview(likeButton)
        stackView.addArrangedSubview(hireButton)
        stackView.addArrangedSubview(messageButton)

        stackView.topAnchor.constraintEqualToAnchor(topSeparatorView.bottomAnchor, constant: 4).active = true
        stackView.widthAnchor.constraintEqualToAnchor(widthAnchor).active = true
        stackView.centerXAnchor.constraintEqualToAnchor(centerXAnchor).active = true

        bottomSeparatorView.topAnchor.constraintEqualToAnchor(stackView.bottomAnchor, constant: 4).active = true
        bottomSeparatorView.widthAnchor.constraintEqualToAnchor(widthAnchor).active = true
        bottomSeparatorView.heightAnchor.constraintEqualToConstant(0.5).active = true


    }



    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}