I have a UICollectionView with custom cells. Everything is working correctly, but what I do not know how to do is assign different text to the labels in each cell. I have one section and three items in each section. I want all three items to have the exact same layout. My thoughts are I need to assign a different identifier for each cell, but I am unsure how I set different text for more than just one cell identifier.
Any help is appreciated, thank you.
let reuseIdentifier = "directionCell"
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 3
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! CustomCollectionViewCell
cell.titleLabel.text = "Current title"
cell.subtitleLabel.text = "Choose to start"
cell.layer.cornerRadius = 10
return cell
If you have 3 cells and 3 cells has different content, just create 3 collectionviewcels and connect IB outlets and then called theme like this :-
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
var cell: UICollectionViewCell!
let reuseIdentifier = "CustomCollectionViewCell"
let cell1 = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! CustomCollectionViewCell
if indexPath.row == 0 {
cell1.titleLabel.text = "Current title"
cell1.subtitleLabel.text = "Choose to start"
cell1.layer.cornerRadius = 10
cell = cell1
} else if indexPath.row == 1 {
cell2.titleLabel.text = "Current title"
cell2.subtitleLabel.text = "Choose to start"
cell2.layer.cornerRadius = 10
cell = cell2
} else {
cell3.titleLabel.text = "Current title"
cell3.subtitleLabel.text = "Choose to start"
cell3.layer.cornerRadius = 10
cell = cell3
}
return cell
}
When you set the numberOfItemsInSection to 3, cellForItemAtIndexPath will also be called 3 times. So, if you have an array of data or information that you want to be displayed then use it in cellForItemAtIndexPath function to get the result that you want. So, assuming you have an array of titles, use that array in
the cellForItemAtIndexPath.
var titles: [String] = ["Title1", "Title2", "Title3"]
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! CustomCollectionViewCell
cell.titleLabel.text = self.titles[indexPath.row]
cell.subtitleLabel.text = "Choose to start"
cell.layer.cornerRadius = 10
return cell
}
Related
How to determine size collection view when I use two different type of cell and the size of one of these cells is always one but other one's size are depend on array and because of that its size is dynamic.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.row == 0 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ProfileCell", for: indexPath) as! ProfileCollectionViewCell
cell.bioLabelText.text = bio
return cell
}else {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CountryCollectionViewCell
cell.countryLabel.text = city
cell.imgView.image = UIImage(named: "lake.jpg")
cell.makeRounded()
return cell
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return uniqueCountryArray.count
}
my ProfileCell number should be one and the number of other cell should be uniqueCountryArray.count. However when I write "return uniqueCountryArray.count + 1" , it gives me error. When I write "return uniqueCountryArray.count" , I missed one array element.
How can I take all of array elements dynamically ? And id array size is 0, I should still show I cell comes from profile Cell.
Change your city = uniqueCountryArray[indexPath.row] to city = uniqueCountryArray[indexPath.row-1] like below
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.row == 0 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ProfileCell", for: indexPath) as! ProfileCollectionViewCell
cell.bioLabelText.text = bio
return cell
}
else {
let city = uniqueCountryArray[indexPath.row-1]
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CountryCollectionViewCell
cell.countryLabel.text = city
cell.imgView.image = UIImage(named: "lake.jpg")
cell.makeRounded()
return cell
}
}
And numberOfItemsInSection will be uniqueCountryArray.count+1
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return uniqueCountryArray.count+1
}
I have two custom cell classes HomeCell & CreateCell. Ideally, the first cell should be the CreateCell & the HomeCell's should start at the index of '1' (After the first create cell) but currently, the CreateCell and the first HomeCell are overlapping. Is there a way I can set the HomeCell's to start at the index of '1'?
If there is any more code that needs to be provided, let me know.
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.row == 0 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CreateCell", for: indexPath) as! CreateCell
//configure your cell here...
return cell
} else {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "HomeCell", for: indexPath) as! HomeCell
cell.list = lists[indexPath.item]
//configure your cell with list
return cell
}
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return lists.count
}
Since you want to access 0th element of List on 1st index, you would need to change the code a little bit in your cellForItemAt indexPath:
cell.list = lists[indexPath.item - 1]
in this way, you will start the HomeCell views from 1st index
Also You would need to change the count of total items, as there is additional create cell.
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return lists.count+1
}
Use indexPath.item in place of indexPath.row
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.item == 0 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CreateCell", for: indexPath) as! CreateCell
//configure your cell here...
return cell
} else {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "HomeCell", for: indexPath) as! HomeCell
cell.list = lists[indexPath.item]
//configure your cell with list
return cell
}
}
I am currently working on a project where I have one CollectionViewController and multiple cells registered. I need assistance with returning the number of cells I want to be shown for the each cell.
For Example I have registered:
collectionView?.register(PhotoCell.self, forCellWithReuseIdentifier: picCell)
collectionView?.register(ArticleCell.self, forCellWithReuseIdentifier: articleCell)
As you can see I have registered two cells. How can I return 7 photo cells and 4 article cells to be displayed in my collection view programmatically?
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 7
}
As of right now I am only able to return 7 photo cells successfully.
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return data.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! PhotoCell //Default will never Execute
if data == photo (
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! PhotoCell
return cell )
else if data == article {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! articleCell
return cell
}
return cell
}
use this approach to determine the cell type . Here Your data if its audio than that cell weill be used and if its article than other cell will be used and count return will be total data count.
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return 11
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
if (indexPath.row < 7)
{
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: picCell, for: indexPath) as? PhotoCell
{
//your code here
return cell
}
}
else if (indexPath.row > 6)
{
//if indexing is needed create new index starting at 0
let articeCellindex = indexPath.row - 7
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: articleCell, for: indexPath) as? ArticleCell
{
return cell
}
}
else
{
return UICollectionViewCell()
}
}
Amey's answer is fine but they omitted how to structure your cell data in a way so that both cell types are contained in one structure. An alternative is to explicitly state which rows will display the cell data. Make sure both the picCell and articleCell reuse identifiers refer to the same cell.
This may be a little confusing, but i have a view controller that has a table view that contains a custom table cell and within this table cell, I have a collectionView with each cell holding a single image. I am trying to configure my collectionCell's image using the userToView variable seen below.
The delegate function below is where the table cell is being configured:
OtherUserAccountViewController.swift
class OtherUserAccountViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var userToView = User()
...
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:OtherUserPhotosTableViewCell = self.tableView.dequeueReusableCell(withIdentifier: photosCellReuseIdentifier) as! OtherUserPhotosTableViewCell
cell.selectionStyle = .none
return cell
}
...
}
The delegate function below is where this image is being set:
OtherUserPhotosTableViewCell.swift
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "otherUserPhotosCollectionCell", for: indexPath) as! OtherUserPhotosCollectionViewCell
//Configure cell with photo from parent ViewController
return cell
}
My custom CollectionViewCell can be seen below:
OtherUserPhotosCollectionViewCell.swift
class OtherUserPhotosCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var imageView: UIImageView!
}
I have only really been getting accustomed to Swift & iOS development over the last couple weeks so any help is much appreciated. Thank you for your time!
Answered by assuming that you have UIImages already available to you
Assuming you have a single UICollectionViewCell
In OtherUserPhotosTableViewCell.swift
var photoFromTableView: UIImage?
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "otherUserPhotosCollectionCell", for: indexPath) as! OtherUserPhotosCollectionViewCell
//Configure cell with photo from parent ViewController
if let photo:UIImage = photoFromTableView {
cell.imageView.image = photo
}
return cell
}
In OtherUserAccountViewController.swift
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:OtherUserPhotosTableViewCell = self.tableView.dequeueReusableCell(withIdentifier: photosCellReuseIdentifier) as! OtherUserPhotosTableViewCell
cell.selectionStyle = .none
cell.photoFromTableView = //Image you want to pass
return cell
}
Assuming you have multiple UICollectionViewCells
In OtherUserPhotosTableViewCell.swift
var photosArray: [UIImage]?
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "otherUserPhotosCollectionCell", for: indexPath) as! OtherUserPhotosCollectionViewCell
//Configure cell with photo from parent ViewController
if let photo_array:[UIImage] = photosArray {
cell.imageView.image = photo_array[IndexPath.row]
}
return cell
}
In OtherUserAccountViewController.swift
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:OtherUserPhotosTableViewCell = self.tableView.dequeueReusableCell(withIdentifier: photosCellReuseIdentifier) as! OtherUserPhotosTableViewCell
cell.selectionStyle = .none
cell.photosArray = //Array of Images you want to pass
return cell
}
I have a problem with a simple collection view: in the delegate didSelectItemAtIndexPath I can't get the right reference to the cell. This is my code:
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int
{
return 1
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return categories.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! CategorySelectionCVCell
cell.titleLabel.text = categories[indexPath.row]["name"] as? String
cell.backgroundColor = ConversionUtilities.getUIColorFrom(categories[indexPath.row]["color"] as! String)
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)
{
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! CategorySelectionCVCell
print("Cell with title: \(cell.titleLabel.text) and background color: \(cell.backgroundColor)")
collectionView.reloadData()
}
I get always when I select a cell:
Cell with title: Optional("Label") and background color: nil
and I don't know why, it's like the cellForItemAtIndexPath is not working but the same print in cellForItemAtIndexPath give me:
Cell with title: Optional("fruits") and background color:
Optional(UIDeviceRGBColorSpace 1 1 0 1)
...and yes, the cell identifier is right is "cell" and I also set up correctly in storyboard. In addition UICollectionViewDataSource and UICollectionViewDelegate are also correctly linked in IB.
Any help?
When you call dequeueReusableCellWithReuseIdentifier method, i.e.
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! CategorySelectionCVCell
you get an empty cell ready to be reused, not the cell that is currently in your collection view.
Although you can get the cell from the collection view by calling
let cell = collectionView!.cellForItemAtIndexPath(indexPath) as! CategorySelectionCVCell
if all you need is the text from its label it's better to go straight to the model, i.e.
let labelText = categories[indexPath.row]["name"] as? String