How to NOT reuse cells in UICollectionView - Swift - ios

I have UICollectionView in a cell of UITableView. This UICollectionView displays user's profile photos. There are only a few items there (let's assume 10 photos is a maximum).
So, I do not want to reload images from backend every time cell reusing. It's inconvenient and unfriendly UX. Therefore, I want to create 10 cells, load images into them and show.
But I don't know how to create (instead of dequeuing) new custom cells within "cellForItem" method of UICollectionView. Or how to forbid reusing.
I'm a kind of newbie in programming, so I would be glad if you explained me that in simple words and most detailed. Thank you.
Here is my code:
Setting CollectinView (uploading random local photos in testing purpose):
extension PhotosTableViewCell: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.row == 0 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "AddPhotoCollectionViewCell", for: indexPath)
return cell
} else {
var cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhotoCollectionViewCell", for: indexPath) as! PhotoCollectionViewCell
cell.photo = UIImage(named: "Photo\(Int.random(in: 1...8))") ?? UIImage(named: "defaultPhoto")
cell.layer.cornerRadius = 10
return cell
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let height = collectionView.frame.height
let width = (height / 16.0) * 10.0
return CGSize(width: width, height: height)
}
}
My custom PhotoCollectionViewCell:
class PhotoCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var heightConstraint: NSLayoutConstraint!
#IBOutlet weak var widthConstraint: NSLayoutConstraint!
var photo: UIImage! {
didSet {
// simulate networking delay
perform(#selector(setImageView), with: nil, afterDelay: Double.random(in: 0.2...1))
// setImageView()
}
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
#objc private func setImageView() {
let cellHeight = self.frame.height
let cellWidth = self.frame.width
let cellRatio = cellHeight / cellWidth
let photoRatio = photo.size.height / photo.size.width
var estimatedWidth = cellWidth
var estimatedHeight = cellHeight
if photoRatio > cellRatio {
estimatedWidth = cellWidth
estimatedHeight = cellWidth * photoRatio
} else {
estimatedHeight = cellHeight
estimatedWidth = cellHeight / photoRatio
}
widthConstraint.constant = estimatedWidth
heightConstraint.constant = estimatedHeight
imageView.image = photo
}
override func prepareForReuse() {
imageView.image = nil
}
}

Just create, fill and return new cell object in cellForItemAt instead of dequeueing it, but it's not a qood practice and you shouldn't do that.

You need to create new cell each time and assign the value to it. Although this is very dangerous thing to do and can cause your app to take so much memory over use your app will use more power and make the device slower.
Instead I suggest that you save your data into a Collection and to keep reusing it as you go.

Related

How to determine the size of collectionviewcell (xib)

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

Loading different heights for cell with UICollectionView

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
}
}
}

CollectionView reloadData() weird behaviour

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()
}
}

Found nil while setting value of a label inside Collection view cell

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

difficulty dealing with the reusability of the collection view cell.

I am trying to create a seating plan using the collection view. In that each seat will have a specific number that means that each cell will have a label that displays the seat number. I am using custom collection view layout to create a seat map and the seat map is 2 way scrollable. Every thing goes well untill the seat map gets scrolled. once the seat map is scrolled the values of the seat numbers are being changed. I know that it is because of the reusability of the collection view cells but i can't find a way out. I tried to search for answer in stack but nothing is working for me. please help..
here is my view controller:
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
#IBOutlet weak var collectionView: UICollectionView!
var seatNo = 0
override func viewDidLoad() {
super.viewDidLoad()
collectionView.dataSource = self
collectionView.delegate = self
}
// func for number of section in collection view
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 15
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell
if indexPath.row == 0 {
seatNo = 1
}
cell.assignSeat(seat: seatNo)
seatNo += 1
cell.seatNumber.text = "\(cell.seat ?? 0)"
return cell
}
}
and here is my collection view cell :
class CollectionViewCell: UICollectionViewCell {
#IBOutlet weak var seatNumber: UILabel!
var seat: Int?
override func prepareForReuse() {
seatNumber.text = ""
seat = 0
}
func assignSeat(seat: Int) {
self.seat = seat
}
}
and if needed here is the code for the custom Collection View Layout:
class CustomCollectionLayout: UICollectionViewLayout {
// var for cell height
var CELL_HEIGHT: Double!
//Variable for cell width
var CELL_WIDTH: Double!
// Variable for the status bar height
let STATUS_BAR = UIApplication.shared.statusBarFrame.height
// Array to store the cell attributes
var cache = [UICollectionViewLayoutAttributes]()
//variable to define the content size
var contentSize = CGSize.zero
// another variable to store the cell atributes
var cellAttrsDictionary = [UICollectionViewLayoutAttributes]()
// variable to store the cell padding
var cellPadding: Double!
// func that defines the collection view content size
override var collectionViewContentSize: CGSize{
return self.contentSize
}
// func to prepare the collection view
// how the cells are to be mapped is defined in this function
override func prepare() {
// assigning the values to the variables
CELL_HEIGHT = 44
CELL_WIDTH = 44
cellPadding = 2
// Cycle through each section of the data source.
if collectionView?.isDragging == false{
if collectionView!.numberOfSections > 0 {
for section in 0...collectionView!.numberOfSections-1 {
// Cycle through each item in the section.
if collectionView!.numberOfItems(inSection: section) > 0 {
for item in 0...collectionView!.numberOfItems(inSection: section)-1 {
// storing the index of the current cell
let cellIndex = NSIndexPath(item: item, section: section)
// defining the x and y coordinates for the other cells
let xPos = Double(item) * CELL_WIDTH
let yPos = Double(section) * CELL_HEIGHT
//creating the frame for the cell
let frame = CGRect(x: xPos, y: yPos, width: CELL_WIDTH, height: CELL_HEIGHT)
//providing the padding
let cellFinalAttribute = frame.insetBy(dx:CGFloat(cellPadding) ,dy:CGFloat(cellPadding))
//storing the cellattributes in the array
let cellAttributes = UICollectionViewLayoutAttributes(forCellWith: cellIndex as IndexPath)
cellAttributes.frame = cellFinalAttribute
cellAttrsDictionary.append(cellAttributes)
}
}
}
}
// Update content size.
let contentWidth = Double(collectionView!.numberOfItems(inSection: 0)) * CELL_WIDTH
let contentHeight = Double(collectionView!.numberOfSections) * CELL_HEIGHT
self.contentSize = CGSize(width: contentWidth, height: contentHeight)
}
}
// func that returns the cell attributes for the elements that are visible in the screen
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
// Create an array to hold all elements found in our current view.
var attributesInRect = [UICollectionViewLayoutAttributes]()
// Check each element to see if it should be returned.
for cellAttributes in cellAttrsDictionary {
if rect.intersects(cellAttributes.frame) {
attributesInRect.append(cellAttributes)
}
}
// Return list of elements.
return attributesInRect
}
//func that returns the cell attributes for the indexpath
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
return cellAttrsDictionary[indexPath.row]
}
//this func call the prepare func if the user scrolls if returned true
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
return false
}
}
Rather than using an array, why not say
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell
let seatNo = (indexPath.row + 1) + (indexPath.section * 15)
cell.assignSeat(seat: seatNo)
cell.seatNumber.text = "\(cell.seat ?? 0)"
return cell
}
I haven't ran this code but the idea is to use
indexPath.row + 1
to get the seats position in its row.
then we can use
indexPath.section * 15 // (number of seats per row should be declared static)
to get the count of seats in the previous rows to this one. in the first row the section will be 0 so won't add anything but subsequent rows will be added correctly
I highly advise declaring the 15 and 10 at the top of your file to avoid magic numbers

Resources