Trying to add a section at indexPath.row swift - ios

Having a little problem with tableviews. I want to add a section to the tableview without messing with the content of the other data in the table. I want to add (cell3, thiscell) at the 4th indexpath.row. What i have is a section on the storyboard which is one cell that i want to add at the 4th index path without messing with all the other information. How would i use the insert section function? or is there any other way to do it?
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// Table view cells are reused and should be dequeued using a cell identifier.
if indexPath.section == 0 && cell1 == true{
let cellIdentifier = "cell1"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! SubCategoryTableViewCell
cell.nameLabel.text = "cell1"
cell.subNameLabel.text = ""
return cell
} else if indexPath.section == 2 && vally == true{
let cellIdentifier = "cell2"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! SubCategoryTableViewCell
cell.nameLabel.text = "Smiles"
cell.subNameLabel.text = ""
return cell
} else if indexPath.row == 2 {
let cellIdentifier = "cell3"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! thisCell
print("add this after indexpath 2")
return cell
} else if indexPath.section == 1 {
let cellIdentifier = "SubCategoryTableViewCell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! SubCategoryTableViewCell
cell.loading.hidden = false
cell.loading.startAnimating()
cell.nameLabel.text = subCat[indexPath.row].subCategoryName
cell.subNameLabel.text = subCat[indexPath.row].subCategoryDesc
return cell
}
let cell2: SubCategoryTableViewCell = tableView.dequeueReusableCellWithIdentifier("SubCategoryTableViewCell", forIndexPath: indexPath) as! SubCategoryTableViewCell
cell2.userInteractionEnabled = false
return cell2
}
So if there is 10 items in section one when it reach indexpath.row 4 it should insert another section then continue with the other items from section one.

Related

Multiple uitableview in a viewcontroller give an error

i have a problem with the following code that manage two uitableview in a viewcontroller. When insert the data in a modal controller in the 'directionTableView' give a follow error:
Thread 1: signal SIGABRT
'Could not cast value of type 'UITableViewCell' (0x1059e7560) to 'FoodTime.DirectionRecipeTableViewCell' (0x101388bf0). 2018-05-23 21:50:12.160281+0200 FoodTime[4577:360265] Could not cast value of type 'UITableViewCell' (0x1059e7560) to 'FoodTime.DirectionRecipeTableViewCell' (0x101388bf0).'
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
var cell = UITableViewCell()
if (tableView == self.ingredientTableView)
{
let cell = tableView.dequeueReusableCell(withIdentifier: "newIngredientCell", for: indexPath) as! IngredientRecipeTableViewCell
let ingredientCell = ingredients[indexPath.row]
cell.textLabel?.text = ingredientCell.titleIngredientRecipe
cell.detailTextLabel?.text = ingredientCell.subtitleIngredientRecipe
}
else if (tableView == self.directionTableView)
{
//Thread 1: signal SIGABRT on next line
let cell = tableView.dequeueReusableCell(withIdentifier: "newDirectionCell", for: indexPath) as! DirectionRecipeTableViewCell
let directionCell = directions[indexPath.row]
cell.textLabel?.text = directionCell.directionSection
cell.detailTextLabel?.text = directionCell.directionText
}
return cell
}
Away from the problem the first line
var cell = UITableViewCell()
is actually what is being returned cells inside the if statements are local variables
So try this
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
if (tableView == self.ingredientTableView)
{
let cell = tableView.dequeueReusableCell(withIdentifier: "newIngredientCell", for: indexPath) as! IngredientRecipeTableViewCell
let ingredientCell = ingredients[indexPath.row]
cell.textLabel?.text = ingredientCell.titleIngredientRecipe
cell.detailTextLabel?.text = ingredientCell.subtitleIngredientRecipe
return cell
}
else
{
let cell = tableView.dequeueReusableCell(withIdentifier: "newDirectionCell", for: indexPath) as! DirectionRecipeTableViewCell //Thread 1: signal SIGABRT
let directionCell = directions[indexPath.row]
cell.textLabel?.text = directionCell.directionSection
cell.detailTextLabel?.text = directionCell.directionText
return cell
}
}
Also make sure that you register every tableview with the corresponding cell
error i so easy
you declare this
var cell = UITableViewCell()
then you create new one
let cell = tableView.dequeueReusableCell(withIdentifier: "newIngredientCell", for: indexPath) as! IngredientRecipeTableViewCell
just remove let
Also
In interface builder make sure that cell with newDirectionCell is DirectionRecipeTableViewCell and same for another cell
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
var cell = UITableViewCell()
if (tableView == self.ingredientTableView)
{
cell = tableView.dequeueReusableCell(withIdentifier: "newIngredientCell", for: indexPath) as! IngredientRecipeTableViewCell
let ingredientCell = ingredients[indexPath.row]
cell.textLabel?.text = ingredientCell.titleIngredientRecipe
cell.detailTextLabel?.text = ingredientCell.subtitleIngredientRecipe
}
else if (tableView == self.directionTableView)
{
//Thread 1: signal SIGABRT on next line
cell = tableView.dequeueReusableCell(withIdentifier: "newDirectionCell", for: indexPath) as! DirectionRecipeTableViewCell
let directionCell = directions[indexPath.row]
cell.textLabel?.text = directionCell.directionSection
cell.detailTextLabel?.text = directionCell.directionText
}
return cell
}

How to prevent repeating the same code in cellForRowAt

Can you please help me to find a solution and not to copy the same code again and again? Now I do have this code
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: productImageCell, for: indexPath) as! ProductImageCell
if let product = self.product {
cell.product = product
}
cell.selectionStyle = .none
return cell
} else if indexPath.row == 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: productDetailCell, for: indexPath) as! ProductDetailCell
cell.backgroundColor = UIColor.lightGray
if let product = self.product {
cell.product = product
}
cell.selectionStyle = .none
return cell
} else if indexPath.row == 2 {
let cell = tableView.dequeueReusableCell(withIdentifier: productDeliveryCell, for: indexPath) as! ProductDeliveryTimeCell
cell.selectionStyle = .none
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: productDeliveryCell, for: indexPath) as! ProductDeliveryTimeCell
cell.selectionStyle = .none
return cell
}
}
As you can see I do copy this part again and again
let cell = tableView.dequeueReusableCell(withIdentifier: productImageCell, for: indexPath) as! ProductImageCell
if let product = self.product {
cell.product = product
}
cell.selectionStyle = .none
return cell
I did try something like that but it is not working
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = UITableViewCell()
if indexPath.row == 0 {
cell = tableView.dequeueReusableCell(withIdentifier: productImageCell, for: indexPath) as! ProductImageCell
} else if indexPath.row == 1 {
cell = tableView.dequeueReusableCell(withIdentifier: productDetailCell, for: indexPath) as! ProductDetailCell
} else if indexPath.row == 2 {
cell = tableView.dequeueReusableCell(withIdentifier: productDeliveryCell, for: indexPath) as! ProductDeliveryTimeCell
} else {
cell = tableView.dequeueReusableCell(withIdentifier: productDeliveryCell, for: indexPath) as! ProductDeliveryTimeCell
}
if let product = self.product {
cell.product = product
}
cell.selectionStyle = .none
return cell
}
include product property in all cells. Remove indexpath.row == 2 block, it does nothing.
write code like this ,
if indexPath.row == 1 {
var cell = tableView.dequeueReusableCell(withIdentifier: productImageCell, for: indexPath) as! ProductImageCell
cell.product == "" //clear product field for reusing property
if let product = self.product {
cell.product = product
}
cell.selectionStyle = .none
return cell
} else if .....
//You need to use same class in multiple cell as like,
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell:HomeCell!
if homeArray[indexPath.row]["type"] == "1" {
cell = tableView.dequeueReusableCell(withIdentifier: "ProductTitleCell", for: indexPath) as! HomeCell
}
else if homeArray[indexPath.row]["type"] == "2" {
cell = tableView.dequeueReusableCell(withIdentifier: "ProductImageCell", for: indexPath) as! HomeCell
}
cell.lbl_Title_1.text = homeArray[indexPath.row]["product_name"]
if cell.tag == 2 {
cell.imageview_1.image = UIImage(named: homeArray[indexPath.row]["product_image"]!)
}
return cell
}

ios swift uitableview add last cell

I want to add a cell into my tableview to the last row using another UserInterface.The code is like this.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:JoinCell = tableView.dequeueReusableCellWithIdentifier(reuseIdentifier, forIndexPath: indexPath) as! JoinCell
let lastSectionIndex = tableView.numberOfSections-1
let lastSectionLastRow = tableView.numberOfRowsInSection(lastSectionIndex) - 1
let lastIndexPath = NSIndexPath(forRow:lastSectionLastRow, inSection: lastSectionIndex)
let cellIndexPath = tableView.indexPathForCell(cell)
if cellIndexPath == lastIndexPath {
cell = tableView.dequeueReusableCellWithIdentifier("JoinFooterCell") as! JoinFooterCell
}
I got error message "Cannot assign value of type 'JoinFooterCell' to type 'JoinCell'"
Does anyone can give me advise? Thanks.
Do this and for datasource.sections.count use the same value you return in numberOfSectionInTableView() and for datasource.rows.count use the same value you return in your numberOfRowsForSection()
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if datasource.sections.count - 1 == indexPath.section && datasource.rows.count - 1 == indexPath.row {
let cell = tableView.dequeueReusableCellWithIdentifier("JoinFooterCell") as! JoinFooterCell
return cell
} else {
let cell = tableView.dequeueReusableCellWithIdentifier(reuseIdentifier, forIndexPath: indexPath) as! JoinCell
return cell
}
}
Do something like this
let lastSectionIndex = tableView.numberOfSections-1
let lastSectionLastRow = tableView.numberOfRowsInSection(lastSectionIndex) - 1
let lastIndexPath = NSIndexPath(forRow:lastSectionLastRow, inSection: lastSectionIndex)
let cellIndexPath = tableView.indexPathForCell(cell)
var cell
if cellIndexPath == lastIndexPath {
cell = tableView.dequeueReusableCellWithIdentifier("JoinFooterCell") as! JoinFooterCell
}
else {
cell = tableView.dequeueReusableCellWithIdentifier(reuseIdentifier, forIndexPath: indexPath) as! JoinCell
}
What actually am trying to do is create cell which you want to return. Don't initialize the cell first and then try to re assign. First determine whether its the last cell and based on that, initialize the kind of cell you want.
Let try this:
var cell: UITableViewCell!
if cellIndexPath == lastIndexPath {
cell = tableView.dequeueReusableCellWithIdentifier("JoinFooterCell") as! JoinFooterCell
} else {
cell = tableView.dequeueReusableCellWithIdentifier(reuseIdentifier, forIndexPath: indexPath) as! JoinCell
}
return cell

Trying to add a section every 2 indexPath.row swift

Having a little problem with tableviews. I want to add a section to the tableview without messing with the content of the other data in the table. I want to add (cell3, thiscell) after every 2 indexpath.row
What i have is a section on the storyboard which is one cell that i want to add after every 2 index path without messing with all the other information. How would i use the insert section function? or is there any other way to do it?
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// Table view cells are reused and should be dequeued using a cell identifier.
if indexPath.section == 0 && cell1 == true{
let cellIdentifier = “cell1"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! SubCategoryTableViewCell
cell.nameLabel.text = “cell1"
cell.subNameLabel.text = ""
return cell
} else if indexPath.section == 2 && vally == true{
let cellIdentifier = "cell2"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! SubCategoryTableViewCell
cell.nameLabel.text = “Smiles"
cell.subNameLabel.text = ""
return cell
} else if indexPath.row == 2 {
let cellIdentifier = “cell3"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! thisCell
print("add this after indexpath 2")
return cell
} else if indexPath.section == 1 {
let cellIdentifier = "SubCategoryTableViewCell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! SubCategoryTableViewCell
cell.loading.hidden = false
cell.loading.startAnimating()
cell.nameLabel.text = subCat[indexPath.row].subCategoryName
cell.subNameLabel.text = subCat[indexPath.row].subCategoryDesc
return cell
}
let cell2: SubCategoryTableViewCell = tableView.dequeueReusableCellWithIdentifier("SubCategoryTableViewCell", forIndexPath: indexPath) as! SubCategoryTableViewCell
cell2.userInteractionEnabled = false
return cell2
}
You want to display for cell3 for indexPath.row = 2 in all sections or any specific section?
In case if you want to display in all sections:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// Table view cells are reused and should be dequeued using a cell identifier.
if(indexPath.row == 2){
let cellIdentifier = "cell3"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! thisCell
print("add this after indexpath 2")
return cell
}
else if indexPath.section == 0 && cell1 == true{
let cellIdentifier = "cell1"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! SubCategoryTableViewCell
cell.nameLabel.text = “cell1"
cell.subNameLabel.text = ""
return cell
} else if indexPath.section == 2 && vally == true{
let cellIdentifier = "cell2"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! SubCategoryTableViewCell
cell.nameLabel.text = “Smiles"
cell.subNameLabel.text = ""
return cell
} else if indexPath.section == 1 {
let cellIdentifier = "SubCategoryTableViewCell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! SubCategoryTableViewCell
cell.loading.hidden = false
cell.loading.startAnimating()
cell.nameLabel.text = subCat[indexPath.row].subCategoryName
cell.subNameLabel.text = subCat[indexPath.row].subCategoryDesc
return cell
}
let cell2: SubCategoryTableViewCell = tableView.dequeueReusableCellWithIdentifier("SubCategoryTableViewCell", forIndexPath: indexPath) as! SubCategoryTableViewCell
cell2.userInteractionEnabled = false
return cell2
}
And above code will add new cell cell3 in each section at indexPath.row -> 2
The indexPath.row value is intended to match indexes your underlying array of supporting data. Presenting additional "virtual" cells in place of rows does not add them, it merely shows a different cell at the corresponding row.
You have two choices:
1) take into account the progressive offset that your "in-between" cells create in the subCat[row] and the IndexPath.row.
2) use actual sections and segment and mat pairs of entries to indexPath.row 0 and 1 in each section.
For #1, you could create a pair of mapping functions and use them to convert indexPath.row to and from indexes in subCat[]
func indexFromRow(row:int) -> int?
{ return row % 3 == 2 ? nil : row - row/3 }
func rowFromIndex(index:Int) -> Int
{ return index + index/2 }
Then, when returning you cell, you can use the functions to establish the correspondance between rows and indexes:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
if let subCatIndex = indexFromRow(indexPath.row)
{
// build a SubCategoryTableViewCell cell, feed it with subCat[subCatIndex] data and return it
}
else
{
// build a thisCell cell and return it
}
}
you will also need to adjust the number of rows returned for the section to make room for the intermediate cells
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{ return rowForIndex(subCat.count-1) + 1 }
Everywhere in you code where you receive an IndexPath and need to know the index in subCat[], you'll need to use the rowToIndex() function
When you want to know the index path of an item in subCat[] at a given index, you'll have to us indexToRow() to build the indexPath
For #2, you will have to use a similar technique to map indexPath.row and indexes in subCat[], but you'll also have to deal with sections and I don't think you can use a reusable cell for section headers.

Sub-Class multiple Cells

In my UITableView I have Four cell. Each cell has its own class. But I can only return one of the cells. Here is my code
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let firstCell = tableView.dequeueReusableCellWithIdentifier("FirstCell", forIndexPath: indexPath) as! FirstTableViewCell
let secondCell = tableView.dequeueReusableCellWithIdentifier("SecondCell", forIndexPath: indexPath) as! SecondTableViewCell
let thirdCelll = tableView.dequeueReusableCellWithIdentifier("ThirdCell", forIndexPath: indexPath) as! ThirdTableViewCell
let fourthCell = tableView.dequeueReusableCellWithIdentifier("FourthCell", forIndexPath: indexPath) as! FourthTableViewCell
return firstCell
}
How do I Correctly sub class and return them
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.row == 0 // or your custom condition
{ let firstCell = tableView.dequeueReusableCellWithIdentifier("FirstCell", forIndexPath: indexPath) as! FirstTableViewCell
return firstCell
}
else if indexPath.row == 1{
let secondCell = tableView.dequeueReusableCellWithIdentifier("SecondCell", forIndexPath: indexPath) as! SecondTableViewCell
return secondCell
}
indexPath.row == 2{
let thirdCelll = tableView.dequeueReusableCellWithIdentifier("ThirdCell", forIndexPath: indexPath) as! ThirdTableViewCell
return thirdCelll
}
else{
let fourthCell = tableView.dequeueReusableCellWithIdentifier("FourthCell", forIndexPath: indexPath) as! FourthTableViewCell
return fourthCell
}
}
This function is called multiple times. The indexPath.row would be used to determine which cell to return. You should check the value of this and only return the requested cell.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell
switch indexPath.row {
case 0:
cell = tableView.dequeueReusableCellWithIdentifier("FirstCell", forIndexPath: indexPath) as! FirstTableViewCell
case 1:
cell = tableView.dequeueReusableCellWithIdentifier("SecondCell", forIndexPath: indexPath) as! SecondTableViewCell
case 2:
cell = tableView.dequeueReusableCellWithIdentifier("ThirdCell", forIndexPath: indexPath) as! ThirdTableViewCell
case 3:
cell = tableView.dequeueReusableCellWithIdentifier("FourthCell", forIndexPath: indexPath) as! FourthTableViewCell
}
return cell;
}

Resources