based on the screen shot, I will have a big collectionview to contain few cells (with colors). All cell will display only one time in the view except for the green one.The green one will display an array of users.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.item == 0{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: topfeatureCellIndent, for: indexPath) as! topFeatureCell
//configure if needed
return cell
}else if indexPath.item == 1{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: userCellIdent, for: indexPath) as! featureUserContainerViewCell
cell.featureUsers = featureUser
cell.selectUserdelegate = self
return cell
}else if indexPath.item == 2{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ticketLabelIdent, for: indexPath) as! ticketLabelCell
return cell
} else if indexPath.item == 3{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: whosgoingIdent, for: indexPath) as! whoGoingCell
cell.config(withTimer: timeleft)
return cell
}
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: allUserCellIdent, for: indexPath) as! allUserCell
let index = indexPath.item - 4
let user = allPartyUserArr![index]
cell.config(withUser: user)
return cell
The way I need to display the last cell is by implement the code above but I think its not correct, because what if I want to add in other cells after displaying all the cells, is there any better way to dequeue the cell properly?
I would suggest you to use 2 Sections in UICollectionView.
keep all the one-time visible cells in section 0 and the cells which will represent array for users in section 1
This is how you can set number of sections
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 2
}
To set Header of each section you can implement below functions and set any size for your header. CGSizeMake(0, 0) will hide the Header
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
return CGSize(width : 0, height : 0) // Header size
}
then number of items in each section
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if section == 0 {
return 4
}
else {
users.count
}
//return (section == 0) ? 4 : users.count
}
to display cell
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.section == 0 {
// Based on Your implementation
if indexPath.item == 0{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: topfeatureCellIndent, for: indexPath) as! topFeatureCell
//configure if needed
return cell
}else if indexPath.item == 1{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: userCellIdent, for: indexPath) as! featureUserContainerViewCell
cell.featureUsers = featureUser
cell.selectUserdelegate = self
return cell
}else if indexPath.item == 2{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ticketLabelIdent, for: indexPath) as! ticketLabelCell
return cell
} else if indexPath.item == 3{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: whosgoingIdent, for: indexPath) as! whoGoingCell
cell.config(withTimer: timeleft)
return cell
} else {
return UICollectionViewCell()
}
}else{
//make sure the identifier of your cell for second section
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: allUserCellIdent, for: indexPath) as! allUserCell
// populate your user cell here
return cell
}
}
You can set the number of sections in CollectionView like this :
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 5
}
Set number of items in each section :
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
switch section {
case 0:
return 1
default:
return 3
}
}
Number of items you can set according to the section.
and for cells in each section :
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
switch indexPath.section {
case 0:
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: topfeatureCellIndent, for: indexPath) as! topFeatureCell
//configure if needed
return cell
case 1:
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: userCellIdent, for: indexPath) as! featureUserContainerViewCell
cell.featureUsers = featureUser
cell.selectUserdelegate = self
return cell
case 2:
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ticketLabelIdent, for: indexPath) as! ticketLabelCell
return cell
case 3:
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: topfeatureCellIndent, for: indexPath) as! topFeatureCell
//configure if needed
return cell
case 4:
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: whosgoingIdent, for: indexPath) as! whoGoingCell
cell.config(withTimer: timeleft)
return cell
default:
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: allUserCellIdent, for: indexPath) as! allUserCell
let index = indexPath.item - 4
let user = allPartyUserArr![index]
cell.config(withUser: user)
return cell
}
}
Hope this helps or else you can google for more better tutorials and solutions.
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 a UICollectionView with 4 UICollectionViewCells. Each cell contains a UITableView with a varying number of cells.
I have an array from which I need to pass a value (depending on the indexPath) into the cell. My problem is that it always gives me nil when I try to do this.
So for example I have this array:
let arrayOfStrings = ["test1", "test2", "test3", "test4"]
I have this code in my collection view's cellForItemAt method:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "testCollectionViewCell", for: indexPath) as! TestCollectionViewCell
cell.myString = arrayOfStrings[indexPath.row]
cell.label.text = "This text is set."
return cell
}
The cell's label is set properly, but when I try to print myString in the cell's table view's cellForRowAt method it always returns nil.
I need the string because I plan to manipulate the table views depending on the string passed in.
So why is this happening and what can be done?
You can try like this
extension HomeViewController : UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 4
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "DealTableViewCell", for: indexPath) as! DealTableViewCell
cell.DealCollectionView.dataSource = self
cell.DealCollectionView.delegate = self
cell.DealCollectionView.tag = 10101
return cell
} else if indexPath.row == 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: "BusinessTableViewCell", for: indexPath) as! BusinessTableViewCell
cell.BusinessCollectionView.dataSource = self
cell.BusinessCollectionView.delegate = self
cell.BusinessCollectionView.tag = 10102
return cell
} else if indexPath.row == 2 {
let cell = tableView.dequeueReusableCell(withIdentifier: "FilterTableViewCell", for: indexPath) as! FilterTableViewCell
cell.FilterCollectionView.dataSource = self
cell.FilterCollectionView.delegate = self
cell.FilterCollectionView.tag = 10103
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "ComboTableViewCell", for: indexPath) as! ComboTableViewCell
cell.ComboCollectionView.dataSource = self
cell.ComboCollectionView.delegate = self
cell.ComboCollectionView.tag = 10104
return cell
}
}
}
Add the collection view to each tableview cell and set delegate in tableview cell
extension HomeViewController : UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if collectionView.tag == 10101 {
return 3
} else if collectionView.tag == 10102 {
return 3
} else if collectionView.tag == 10103 {
return 3
} else if collectionView.tag == 10104 {
return 3
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView.tag == 10101 {
let cell = collectionView.dequeueReusableCell(withIdentifier: "DealCollectionViewCell", for: indexPath) as! DealCollectionViewCell
return cell
} else if collectionView.tag == 10102 {
let cell = collectionView.dequeueReusableCell(withIdentifier: "BusinessCollectionViewCell", for: indexPath) as! BusinessCollectionViewCell
return cell
} else if collectionView.tag == 10103 {
let cell = collectionView.dequeueReusableCell(withIdentifier: "FilterCollectionViewCell", for: indexPath) as! FilterCollectionViewCell
return cell
} else if collectionView.tag == 10104 {
let cell = collectionView.dequeueReusableCell(withIdentifier: "ComboCollectionViewCell", for: indexPath) as! ComboCollectionViewCell
return cell
}
return UICollectionViewCell()
}
}
For reload the collectionView in use
if let cell = self.tableView.cellForRow(at: IndexPath(row: i, section: 0)) as?
tableViewCell {
cell.collectionView.reloadData()
}
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 have two custom UICollectionViewCells(AddImageCollectionViewCell, ItemCollectionViewCell) which I am loading depending on indexpath. Here is my code for the cellForItemAtIndexpath-
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
var cell :UICollectionViewCell!
if indexPath.row == 0{
cell = collectionView.dequeueReusableCell(withReuseIdentifier: "addImageCell", for: indexPath) as! AddImageCollectionViewCell
}
else{
cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ItemCell", for: indexPath) as! ItemCollectionViewCell
cell.contentImage = self.droppedItemList[indexPath.row] //error here
}
return cell
}
I am getting the error as "Value of type 'UICollectionViewCell?' has no member 'contentImage'". Why is my cell in the else clause is not cast to "ItemCollectionViewCell" type.
I know, I must be doing something very foolish. I would be really grateful if someone can point me to the right direction.
You are declaring cell as basic type UICollectionViewCell, that's the reason. Return the cells separately
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.row == 0 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "addImageCell", for: indexPath) as! AddImageCollectionViewCell
return cell
} else {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ItemCell", for: indexPath) as! ItemCollectionViewCell
cell.contentImage = self.droppedItemList[indexPath.row]
return cell
}
}
I'm attempting to create a custom cell at the end of my UICollectionViewCell. The last item should be an "custom cell" so the user can add another record. Tried some solutions but without success. My code so far seems like this:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath as IndexPath) as! EquipamentosCollectionViewCell
if (indexPath as NSIndexPath).row == 0 {
cell.imgEquip?.image = UIImage(named: "novavisita")
return cell
}else{
cell.backgroundColor = UIColor.green
return cell
}
}
I also tried this solution, but it`s not how I want it to work.
The problem is that it's replacing the first.
Any suggestions of how to do that?
Then add that cell at last:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath as IndexPath) as! EquipamentosCollectionViewCell
if (indexPath as NSIndexPath).item == YOUR_COLLECTION.count - 1{
//Add New Record Cell
cell.imgEquip?.image = UIImage(named: "novavisita")
return cell
}else{
cell.backgroundColor = UIColor.green
return cell
}
}