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).
To create a UICollectionView programmatically, I will create a new instance of UICollectionView by giving it a UICollectionViewFlowLayout as a parameter. var myCollectionView:UICollectionView? The above collection view will not display any items however.
Select the Main storyboard from the file browser. Add a CollectionView by pressing command shift L to open the storyboard widget window. Drag the collectionView onto the main view controller. Add constraints to the UICollectionView widget to ensure that the widget fills the screen on all devices.
A layout object that organizes items into a grid with optional header and footer views for each section.
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") } }
Your problem lies here. In your viewDidLoad()
, you're registering your collectionView cell twice. You are registering the collectionview's cell to your custom cell class in the first line and then in the second line you are registering it to the class UICollectionViewCell
.
collectionView.registerClass(MyCollectionViewCell.self, forCellWithReuseIdentifier: cellReuseIdentifier) collectionView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: "collectionCell")
Just remove the second line and your code should work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With