Case:
I'm using a collection view inside a UIView, I've connected it as an outlet called 'partsCollectionView'. I've created a cell with identifier 'cell' and a custom class 'SelectionCollectionViewCell' for that cell. Inside the cell, I've got a label called 'cellTitle'.
Error: Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
I'm facing the error while setting the value of that label inside 'cellForItemAt' Method.
Here are the concerned views:
Cell description,
and, collection View Description
The Cell Class is:
import UIKit
class SelectionCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var cellTitle: UILabel!
}
The class where I'll use the collection view is:
import UIKit
private let reuseIdentifier = "cell"
let array = ["small","Big","Medium","Very big","Toooo big String","small"]
class SelectionCollectionViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
#IBOutlet weak var partsCollectionView: UICollectionView!
#IBOutlet weak var instructionsView: UITextView!
#IBOutlet weak var image: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
self.partsCollectionView.register(SelectionCollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return array.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = partsCollectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! SelectionCollectionViewCell
cell.layer.cornerRadius = 10
cell.clipsToBounds = true
cell.cellTitle.text = array[indexPath.row]
cell.layer.borderColor = #colorLiteral(red: 0.07843137255, green: 0.6862745098, blue: 0.9529411765, alpha: 0.6819349315)
cell.layer.borderWidth = 2
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let name = array[indexPath.row]
let attributedName = NSAttributedString(string: name)
let width = attributedName.widthWithConstrainedHeight(height: 20.0)
return CGSize(width: width + 40, height: 30.0)
}
}
extension NSAttributedString {
func widthWithConstrainedHeight(height: CGFloat) -> CGFloat {
let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height)
let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, context: nil)
return boundingBox.width
}
}
Update: This is how it looks if I skip setting the title text. The title will come inside those rounded boxes.
Remove this line from viewDidLoad.
self.partsCollectionView.register(SelectionCollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
When you register a cell programmatically it creates a new collection view cell object. It doesn't get the cell from storyboard. So cellTitle will be nil
OR
Programmatically initialize the label in custom collection view cell
class SelectionCollectionViewCell:UICollectionViewCell {
let cellTitle = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(cellTitle)
cellTitle.frame = CGRect(x: 10, y: 10, width: 100, height: 30)
}
}
Just minor mistake is there I think, In cellForItemAt indexPath Please update following line,
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! SelectionCollectionViewCell
I just paste your code and got following output, nothing else,
If you still unable to produce desired output, just delete existing UILabel from SelectionCollectionViewCell and add it again.
FYI. No need to register cell in viewDidLoad() method
Related
Is there a way to measure the width and height of a cell defined in xib from within "sizeforitemat" function or any other function of viewcontroller, once data is dynamically generated? The default layout of the collection view makes it very shabby as depicted in output. Principally layout should have maximally two columns, and the rest of the empty spaces should be divided between cells within a row. So I want to loop over all the items, once it is filled with data to determine the maximum size of amongst cells to generate a layout according to its size. I'll highly appreciate the response.
viewcontroller.swift
import UIKit
class ViewController: UIViewController, UICollectionViewDelegate,
UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
#IBOutlet weak var collectionView: UICollectionView!
let myCell: String = "CollectionViewCell"
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.collectionView.register(UINib(nibName:myCell, bundle: nil), forCellWithReuseIdentifier: myCell)
self.collectionView.delegate = self
self.collectionView.dataSource = self
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
150
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: myCell, for: indexPath) as! CollectionViewCell
cell.lbl1.text = "\(indexPath.row)"
cell.lbl2.text = "\(String(describing: cell.lbl2.text))\(indexPath.row)"
print ("***", indexPath.item, cell.bounds.size, collectionView.frame.size)
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// TODO: measure width and heigth of each cell to find number of columns
return collectionView.frame.size
}
}
collectionviewcell.swift
import UIKit
class CollectionViewCell: UICollectionViewCell {
#IBOutlet weak var lbl1: UILabel!
#IBOutlet weak var lbl2: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
}
viewcontroller's code
xib file's code
collection view cell
output
To find the "widest" cell, you can:
create an instance of your cell
loop through your data, setting the label values
get the width
track the maximum width
Something like this:
let theData: [String] = [
"Short",
"Longer",
"A bit longer",
"ABC",
"This is the longest one",
"Another medium",
"Last one"
]
let nib: UINib = UINib(nibName: "CollectionViewCell", bundle: nil)
let c = nib.instantiate(withOwner: nil, options: nil).first as! CollectionViewCell
var sz: CGSize = .zero
var maxW: CGFloat = 0
for i in 0..<theData.count {
c.lbl1.text = "\(i)"
c.lbl2.text = theData[i]
sz = c.systemLayoutSizeFitting(CGSize(width: .greatestFiniteMagnitude, height: 60.0),
withHorizontalFittingPriority: .defaultLow,
verticalFittingPriority: .required)
maxW = max(maxW, sz.width)
print("Row: \(i)", sz)
}
print("Max Width:", maxW)
Could give this in the debug output:
Row: 0 (50.0, 60.0)
Row: 1 (61.5, 60.0)
Row: 2 (95.5, 60.0)
Row: 3 (42.0, 60.0)
Row: 4 (179.5, 60.0)
Row: 5 (134.5, 60.0)
Row: 6 (73.5, 60.0)
Max Width: 179.5
I am trying to dynamically adjust cells in a CollectionView according to the contents of a label. Basically i have found how to but my challenge is
cellForItemAt method
gets called first before
heightForCellAtIndexPath method
and by doing so this means we are trying to get heights before data is loaded so the cells will always be the same height and therefore we wont achieve different heighted cells
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let content_ = content[indexPath.row]
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "NotesUI", for: indexPath) as! NotesUI
cell.setData(data: content_)
return cell
}
func collectionView(_ collectionView: UICollectionView, heightForCellAtIndexPath indexPath:IndexPath) -> CGFloat {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "NotesUI", for: indexPath) as! NotesUI
return cell.allNoteViews()[indexPath.item - 1].bounds.size.height
}
Essentially in the NotesUI CollectionView class:
class NotesUI:UICollectionViewCell{
#IBOutlet var note: UILabel!
var views: [UILabel] = []
func setData(data: NoteModel){
note.text = data.note
note.numberOfLines = 0
note.lineBreakMode = NSLineBreakMode.byWordWrapping
note.sizeToFit()
views.append(note)
}
func allNoteViews()->[UILabel]{
return views
}
}
I guess my question boils down to how can i call heightForCellAtIndexPath method after the cellForItemAt method so that the CollectionView gets the height of the label after it has contents
You don't need to calculate each cell height if you use auto layout. You can add a vertical stack view to your cell and add your labels to it.
Here is a basic example of self-sizing collection view cells.
class YourCustomCell: UICollectionViewCell {
// Add your labels to this stackView
#IBOutlet weak var yourLabelContainer: UIStackView!
override func awakeFromNib() {
super.awakeFromNib()
yourLabelContainer.translatesAutoresizingMaskIntoConstraints = false
yourLabelContainer.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.size.width - 32).isActive = true // for 16 - 16 padding
}
}
class YourViewController: UIViewController {
#IBOutlet weak var yourCollectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
yourCollectionView.delegate = self
yourCollectionView.dataSource = self
let nib = UINib(nibName: "YourCustomCell", bundle: nil)
yourCollectionView.register(nib, forCellWithReuseIdentifier: "cellReuseId")
if let layout = yourCollectionView.collectionViewLayout as? UICollectionViewFlowLayout {
layout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
}
}
}
I want to make a Collection View with cells, where you can select the colors of my little game. Therefor you can choose between different themes (each in one cell). If the theme is unlocked (by achieving scores), the blur view and the lock-icon should disappear, and all available cells/ themes should be selectable. I implemented this like so:
(Collection ViewController Class:)
import UIKit
import PMSuperButton
class myCollectionViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
#IBOutlet weak var backBtn: UIButton!
let items = ["Default dot", "Trap your first dot", "Score 15 or less (classic)", "Score 5 or less (classic)", "Score 15 or less (hard)", "Score 25 or less (no chill)", "Score 15 or less (snake)", "Score 15 or less everywhere", "Score 10 or less everywhere", "Circle the dot 100 times", "10"]
var preSelected = IndexPath()
#IBOutlet weak var myCollectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
updateUnlockedString()
updateColor()
}
func updateColor(){
view.backgroundColor = myColors().selected(value: selectedInstance.selectedColor).backgroundColor
}
func updateUnlockedString(){
let easyHS = UserDefaults.standard.integer(forKey: "highscoreeasy")
let classicHS = UserDefaults.standard.integer(forKey: "highscoreclassic")
let hardHS = UserDefaults.standard.integer(forKey: "highscorehard")
let nochillHS = UserDefaults.standard.integer(forKey: "highscoreno chill")
let snakeHS = UserDefaults.standard.integer(forKey: "highscoresnake")
var unlockedString = ""
//unimportant steps deleted
UserDefaults.standard.set(unlockedString, forKey: "unlocked")
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return items.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! myCollectionViewCell
if(unlockInstance.unlockedString.contains(String(indexPath.item))){
cell.unlockedEffect()
print("unlocked Effect")
}
cell.label.text = items[indexPath.item]
cell.removeHighlight()
if indexPath.item == selectedInstance.selectedColor{
cell.highlightEffect()
preSelected = IndexPath(item: indexPath.item, section: indexPath.section)
}
cell.setupCellFilling(playerColor: myColors().selected(value: indexPath.item).playerColor, objColor: myColors().selected(value: indexPath.item).objColor, defaultColor: myColors().selected(value: indexPath.item).defaultColor, backgroundColor: myColors().selected(value: indexPath.item).backgroundColor)
myCollectionView = collectionView
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
collectionView.allowsMultipleSelection = false
if ((collectionView.cellForItem(at: indexPath) as! myCollectionViewCell?) != nil) && unlockInstance.unlockedString.contains(String(indexPath.item)){
selectedInstance.selectedColor = indexPath.item
updateColor()
collectionView.reloadData()
}
}
#IBAction func backPressed(_ sender: Any) {
cameInstance.came = true
}
}
(Collection CELL Class:)
import UIKit
class myCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var label: UILabel!
#IBOutlet weak var view: UIView!
#IBOutlet weak var blurView: UIVisualEffectView!
#IBOutlet weak var lockedBlur: UIVisualEffectView!
#IBOutlet weak var lockedIcon: UIImageView!
override func layoutSubviews() {
// cell rounded section
self.layer.cornerRadius = 15.0
self.layer.masksToBounds = true
// cell shadow section
self.contentView.layer.cornerRadius = 15.0
self.contentView.layer.masksToBounds = true
self.layer.shadowColor = myColors().selected(value: selectedInstance.selectedColor).defaultColor.cgColor
self.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
self.layer.shadowRadius = 6.0
self.layer.shadowOpacity = 0.4
self.layer.cornerRadius = 15.0
self.layer.masksToBounds = false
self.layer.shadowPath = UIBezierPath(roundedRect: self.bounds, cornerRadius: self.contentView.layer.cornerRadius).cgPath
super.layoutSubviews()
}
extension myCollectionViewCell{
func highlightEffect(){
self.layer.borderWidth = 5.0
self.layer.borderColor = UIColor.systemGreen.cgColor
}
func removeHighlight(){
self.layer.borderColor = UIColor.clear.cgColor
}
func unlockedEffect(){
lockedBlur.alpha = 0
lockedIcon.alpha = 0
}
func setupCellFilling(playerColor: UIColor, objColor: UIColor, defaultColor: UIColor, backgroundColor: UIColor){
lockedBlur.effect = UIBlurEffect(style: .extraLight)
blurView.effect = UIBlurEffect(style: .systemUltraThinMaterialDark)
lockedIcon.tintColor = objColor
view.backgroundColor = backgroundColor
}
}
The problem
When I open the CollectionView (viewDidLoad), everything appears 100% fine! All cells that should be locked, appear locked (lockedBlur.alpha = 0 and lockedIcon.alpha = 0). Also, only the locked cells are selectable, which I can see with the green border. Only the selected Cell has a green border, thats right.
BUT: When I select a cell, some random locked cells loose their blur view and loose their lock-icon (so blockedBlur and lockedIcon disappear). They still aren't selectable. Sometimes this affects all cells, sometimes only e.g. 2.
When I select a cell, the didSelectItemAt Function gets called. And this also calls updateColors() which only changes the background and calls the mysterious reloadData(). In my opinion the reloadData() SOMEHOW makes the lockedBlur and lockedIcon disappear, and I cannot find why....
Maybe someone can help me..
Thank you!!
SwiftHobby
I am working on Fitness App which has pretty similar working CollectionView behavior for it's training plan section. Basically you select certain cell when you finish an exercise. So I played around a lot with way of implementing selecting and deselecting cells. As I see you are missing selecting and deselecting functions of CollectionViewDelegate. There you set different states Effects
Here is the functions you have to use:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if let cell = collectionView.cellForItem(at: indexPath) as? CustomCollectionViewCell {
cell.showIcon()
}
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
if let cell = collectionView.cellForItem(at: indexPath) as? CustomCollectionViewCell {
cell.hideIcon()
}
}
I'm trying to create my own Book app, and using UICollectionView for listing all the books. Data for each cell is from .plist file, and I'm using custom flowLayout(to make some changes later).
So now I'm stucked with delays and lags when scrolling. I suppose I've made mistakes with passing data to cell or with cell initializing.
Cell created by .xib and custom class, just some layout and UI:
class BookCoverCell: UICollectionViewCell {
#IBOutlet weak var view1: UIView!
#IBOutlet weak var view2: UIView!
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var darkRedView: UIView!
#IBOutlet weak var lightRedView: UIView!
#IBOutlet weak var readButton: UIButton!
#IBOutlet weak var pageLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
clipsToBounds = true
self.backgroundColor = UIColor(white: 1, alpha: 0.0)
view1.layer.cornerRadius = 10
view2.layer.cornerRadius = 10
darkRedView.layer.cornerRadius = 10
lightRedView.layer.cornerRadius = 10
}
}
At ViewController's class:
class MainVC: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UIScrollViewDelegate {
#IBOutlet weak var collectionContainerView: UIView!
#IBOutlet weak var collectionView: UICollectionView!
var books: Array<Book>? {
didSet {
collectionView.reloadData()
}
}
var flowLayout = UICollectionViewFlowLayout()
override func viewDidLayoutSubviews() {
flowLayout = ZoomAndSnapFlowLayout()
collectionView.collectionViewLayout = flowLayout
}
override func viewDidLoad() {
super.viewDidLoad()
collectionContainerView.backgroundColor = UIColor(white: 1, alpha: 0.0)
collectionView.delegate = self
collectionView.dataSource = self
collectionView.register(UINib(nibName: "BookCoverCell", bundle: nil), forCellWithReuseIdentifier: "BookCoverCell");
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
books = BookStore.sharedInstance.loadBooks(plist: "Books")
}
//MARK: UICollectionViewDelegate
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if let books = books {
return books.count
}
return 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "BookCoverCell", for: indexPath) as! BookCoverCell
let book = books![indexPath.row]
let cover = book.coverImage()!
let color = book.getDominantColor()
cell.view1.backgroundColor = color
cell.imageView.image = cover
cell.pageLabel.text = "Pages: 29"
cell.readButton.setTitle("Read", for: .normal)
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let book = books?[indexPath.row]
print ("open")
}
}
And my layout now looks like:
class ZoomAndSnapFlowLayout: UICollectionViewFlowLayout {
var cellWidth = CGFloat()
var cellHeight = CGFloat()
var minLineSpacing = CGFloat()
override init() {
super.init()
self.scrollDirection = .horizontal
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func prepare() {
guard let collectionView = collectionView else { fatalError() }
cellHeight = collectionView.frame.height * 0.8
minLineSpacing = 200
cellWidth = cellHeight
itemSize = CGSize(width: cellWidth, height: cellHeight)
let verticalInsets = (collectionView.frame.height - collectionView.adjustedContentInset.top - collectionView.adjustedContentInset.bottom - itemSize.height) / 2
let horizontalInsets = (collectionView.frame.width - collectionView.adjustedContentInset.right - collectionView.adjustedContentInset.left - itemSize.width) / 2
sectionInset = UIEdgeInsets(top: verticalInsets, left: horizontalInsets, bottom: verticalInsets, right: horizontalInsets)
super.prepare()
}
}
So I'm pretty sure that have some mistakes in my code, but can't find them(( Any suggestion will be helpful for me!
UPDATE:
So first of all thanks!
I've changed my code and replace a really big image with smallest one, and function to get dominant color simply to white color for now, and things already gets better!
BUT there is small lag or delay when first scroll begins, and only with 1st and 2nd cells, while they are scrolling to the left edge of the screen. And after that all cells scrolling without lags, even first two, in both directions (left / right).
Now my code looks like:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "BookCoverCell", for: indexPath) as! BookCoverCell
let book = books![indexPath.row]
let cover = UIImage(named: "flag.png")
let color = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
cell.view1.backgroundColor = color
cell.imageView.image = cover
cell.pageLabel.text = "Pages: 29"
cell.readButton.setTitle("Read", for: .normal)
return cell
}
and UPDATE #2
removing
flowLayout = ZoomAndSnapFlowLayout()
collectionView.collectionViewLayout = flowLayout
to viewWillAppear() fix these small lags too!! Hooray!)
Read this article about Time Profiling and collection view: https://voxels.github.io/eliminating-collection-view-tearing-with-xcode-time-profiler-instrument
Since your implementation is very simple, there aren't many things that could be wrong, but you probably have the same issue that the author of the article had -- the images themselves are very large, and need to be read and resized.
They solved the issue by making appropriately sized versions of the images.
In your case getDominantColor will also be slower on large images (I am assuming that it reads the pixels to get the dominant color. You should also consider caching this color and not recalculating it every time (if you are not already doing that).
I tried to change the text of my label inside an UICollectionViewCell. The ViewCell class is linked to the cell, the outlets are set and in the viewController its registered by
// Register cell classes
self.collectionView!.register(ImageCollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
and in cellForItemAt...
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! ImageCollectionViewCell
but I can't access the label. Same problem with an imageView. If I tried to set the text with:
cell.hund.text = "bla"
the label "hund" is known but it throws that the label is nil.
Thanks Tom
ImageCollectionVC
import UIKit
private let reuseIdentifier = "cell"
class ImageCollectionVC: UICollectionViewController {
var listOfImages = [Int: KKImage]()
override func viewDidLoad() {
super.viewDidLoad()
// Register cell classes
self.collectionView!.register(ImageCollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
listOfImages = xmlParseImageSource()
}
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return listOfImages.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! ImageCollectionViewCell
let imgUrl = listOfImages[indexPath.row]?.imagePreviewUrl
do {
let bindData = try Data(contentsOf: imgUrl!)
let img = UIImage(data: bindData)
cell.hund.text = "bla"
//cell.img.image = img
//cell.img.image = UIImage(data: bindData)
} catch {
print(error.localizedDescription)
}
cell.backgroundColor = UIColor.blue
return cell
}
}
ImageCollectionViewCell
import UIKit
class ImageCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var img: UIImageView!
#IBOutlet weak var hund: UILabel!
}
Thomas in awake from nib just initialize your UIImageView and UILabel and add them to the cell, it should work :)
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code, you obviously need to set the frames/constraints as per your requirement
img = UIImageView(frame: CGRect(x: 0, y: 0, width: 44, height: 44))
hund = UILabel(frame: CGRect(x: 50, y: 0, width: 300, height: 40))
self.addSubview(img)
self.addSubview(hund)
}
In case you are using an xib don't register the class instead use the nib registration which should be:
self.collectionView.register(UINib.init(nibName: "ImageCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: reuseIdentifier )