I am creating a TableView that starts with an image at the top, approximately 5 cells of parsed json, another image, approximately 3 more cells of parsed json, and another image.
I have 3 custom nibs that I am using. Each one is unique.
I get an "Index out of range" error on the line "let item = page?.collapsibles[indexForSecondSetTableViewCells]"
Here is my code:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let currentIndex = indexPath.row - 1
let numberofCarousels = self.page?.carousels.count
let indexAfterCarousels = numberofCarousels ?? 00 + 1
let indexForSecondSetTableViewCells = indexAfterCarousels + 1
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "pipesOne", for: indexPath) as! Pipes1TableViewCell
cell.pipesOne.image = UIImage(named: "WhatsNew1")
return cell
}
if indexPath.row == indexAfterCarousels {
let cell = tableView.dequeueReusableCell(withIdentifier: "pipesOne", for: indexPath) as! Pipes1TableViewCell
cell.pipesOne.image = UIImage(named: "WhatsNew2")
return cell
}
if indexPath.row == indexForSecondSetTableViewCells {
let cell = tableView.dequeueReusableCell(withIdentifier: "collapsibleCell", for: indexPath) as! CollapsiblesTableViewCell
let item = page?.collabsible[indexForSecondSetTableViewCells]
cell.collabsibleTitle.text = item?.title
cell.collabsibleDescription.text = item?.content
return cell
}
let cell = tableView.dequeueReusableCell(withIdentifier: "newsTableViewCell", for: indexPath) as! NewsTableViewCell
let item = page?.carousels[currentIndex]
cell.newsTitle.text = item?.title
cell.newsText.text = item?.caption
cell.newsImage.kf.setImage(with: page?.carousels[currentIndex].imageURL)
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (page?.carousels.count ?? 0) + 1 + (page?.collapsibles.count ?? 0)
}
Update: I simplified the code to use the same json object twice and so that each item maps to exactly the cell that it should go to and I still get the "Fatal error: Index out of range" error at row 7 with let item = page?.collapsible[indexPath.row]
New code:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "pipesOne", for: indexPath) as! Pipes1TableViewCell
cell.pipesOne.image = UIImage(named: "WhatsNew1")
return cell
}
if indexPath.row == 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: "newsTableViewCell", for: indexPath) as! NewsTableViewCell
let item = page?.carousels[indexPath.row]
cell.newsTitle.text = item?.title
cell.newsText.text = item?.caption
cell.newsImage.kf.setImage(with: page?.carousels[indexPath.row].imageURL)
return cell
}
if indexPath.row == 6 {
let cell = tableView.dequeueReusableCell(withIdentifier: "pipesOne", for: indexPath) as! Pipes1TableViewCell
cell.pipesOne.image = UIImage(named: "WhatsNew2")
return cell
}
if indexPath.row == 7 {
let cell = tableView.dequeueReusableCell(withIdentifier: "collapsibleCell", for: indexPath) as! CollapsiblesTableViewCell
let item = page?.collapsibles[indexPath.row]
cell.collabsibleTitle.text = item?.title
cell.collabsibleDescription.text = item?.content
return cell
}
return UITableViewCell()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 11
}
Try to print("\(indexPath)") in
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print("\(indexPath)")
}
Then you will know how many rows it successfully shows before crash.
Then in cellForRowAt put conditional break point such it stops when indexPath is the one it crashed.
Now do po (page?.carousels.count ?? 0) + 1 + (page?.collapsibles.count ?? 0)
to see how many rows your tableview has. Most definitely indexForSecondSetTableViewCells is more than the number of rows
Related
I have been trying to use static cells using XIB's ,But in cell for row at index path I am getting an error like "Cannot convert return expression of type 'UITableViewCell.Type' to return type 'UITableViewCell'" at the line of " return UITableViewCell".Can any one help me to do this ,Thanks in advance.
extension TriipDetailsViewController: UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0
{
let cell : TripDriverDetailsCell = tripDetailsTableView.dequeueReusableCell(withIdentifier: "TripDriverDetailsCell", for: indexPath) as! TripDriverDetailsCell
return cell
}else if indexPath.row == 1 {
let cell : TripFareDetailsCell = tripDetailsTableView.dequeueReusableCell(withIdentifier: "TripFareDetailsCell", for: indexPath) as! TripFareDetailsCell
return cell
}else if indexPath.row == 2 {
let cell : TripPaymentModeCell = tripDetailsTableView.dequeueReusableCell(withIdentifier: "TripPaymentModeCell", for: indexPath) as! TripPaymentModeCell
return cell
}
return UITableViewCell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.row == 0{
return 230
}else if indexPath.row == 1{
return 200
}else if indexPath.row == 2{
return 120
}
}
}
Eliminate the return UITableViewCell.
Some people might say return UITableViewCell(), but I’d rather handle this case as the error that it really is, e.g.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch indexPath.row {
case 0:
return tableView.dequeueReusableCell(withIdentifier: "TripDriverDetailsCell", for: indexPath)
case 1:
return tableView.dequeueReusableCell(withIdentifier: "TripFareDetailsCell", for: indexPath)
case 2:
return tableView.dequeueReusableCell(withIdentifier: "TripPaymentModeCell", for: indexPath)
default:
fatalError("Unexpected row number \(indexPath.row)")
}
}
The heightForRowAt should similarly handle the scenario where the indexPath.row is not 0, 1, or 2, e.g.:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
switch indexPath.row {
case 0: return 230
case 1: return 200
case 2: return 120
default: fatalError("Unexpected row number \(indexPath.row)")
}
}
let cell : UITableViewCell
if indexPath.row == 0
{
cell = tripDetailsTableView.dequeueReusableCell(withIdentifier: "TripDriverDetailsCell", for: indexPath) as! TripDriverDetailsCell
}else if indexPath.row == 1 {
cell = tripDetailsTableView.dequeueReusableCell(withIdentifier: "TripFareDetailsCell", for: indexPath) as! TripFareDetailsCell
}else if indexPath.row == 2 {
cell = tripDetailsTableView.dequeueReusableCell(withIdentifier: "TripPaymentModeCell", for: indexPath) as! TripPaymentModeCell
}else {
cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
}
return cell
}
You've got
Cannot convert return expression of type 'UITableViewCell.Type' to return type 'UITableViewCell
because you return a cell as return UITableViewCell that means you return a whole UITableViewCell class instead of single UITableViewCell() therefore in the last you've to return cell as return UITableViewCell()
e.g.
extension TriipDetailsViewController: UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0
{
let cell : TripDriverDetailsCell = tripDetailsTableView.dequeueReusableCell(withIdentifier: "TripDriverDetailsCell", for: indexPath) as! TripDriverDetailsCell
return cell
}else if indexPath.row == 1 {
let cell : TripFareDetailsCell = tripDetailsTableView.dequeueReusableCell(withIdentifier: "TripFareDetailsCell", for: indexPath) as! TripFareDetailsCell
return cell
}else if indexPath.row == 2 {
let cell : TripPaymentModeCell = tripDetailsTableView.dequeueReusableCell(withIdentifier: "TripPaymentModeCell", for: indexPath) as! TripPaymentModeCell
return cell
}
return UITableViewCell() //Here you've to change
}
I'm trying to add two prototype cell on my UITableView. However, I don't know how I could verify to be able to "return" the correct cells for each prototype. Can you guys give me a hand?
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if ??? {
let cell = itensTableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! tableviewCell
cell.nameCell.text = "Oculos"
return cell
}else{
let cellAdicionar = itensTableView.dequeueReusableCell(withIdentifier: "cellIdAdc", for: indexPath) as! tableviewBotaoAdicionar
cellAdicionar.botaoAdicionar.text = "Adicionar"
return cellAdicionar
}
}
Storyboard Picture
You need to set your model to answer that inside cellForRowAt
var arr = ["first","second","first"]
//
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let item = arr[indexPath.row]
if item == "first" {
let cell = itensTableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! tableviewCell
cell.nameCell.text = "Oculos"
return cell
} else {
let cellAdicionar = itensTableView.dequeueReusableCell(withIdentifier: "cellIdAdc", for: indexPath) as! tableviewBotaoAdicionar
cellAdicionar.botaoAdicionar.text = "Adicionar"
return cellAdicionar
}
}
var mutipleArrayForFirstCell:[String] = ["1","2","3","4","5","6","7","8","9","10"]
var mutipleArrayForSecondCell:[String] = ["11","12","13","14","15","16","17","18","19","20"]
//MARK - TableView delegates
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 1 {
return mutipleArrayForFirstCell.count
}else {
return mutipleArrayForSecondCell.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let valueAt1stCell = tableView.dequeueReusableCell(withIdentifier: "FirstCell", for: indexPath) as! multipleCustomCellTableViewCell
valueAt1stCell.Firstlabel.text = mutipleArrayForFirstCell[indexPath.row]
return valueAt1stCell
} else {
let valueAt2ndCell = tableView.dequeueReusableCell(withIdentifier: "SecondCell", for: indexPath) as! SecondCustomTableviewCell
valueAt2ndCell.secondLabel.text = mutipleArrayForSecondCell[indexPath.row]
return valueAt2ndCell
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
My questions is i want to show the above declared two array value in two different cells. How can i do it?? it showing like this:
But it should show 1-10 in one cell and 11-20 in another cell.someone please help me ,Thanks in advance
how can i give some space between two cells ?
Try this one
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch indexPath.section {
case 0:
//First Array
let valueAt1stCell = tableView.dequeueReusableCell(withIdentifier: "FirstCell", for: indexPath) as! multipleCustomCellTableViewCell
valueAt1stCell.Firstlabel.text = mutipleArrayForFirstCell[indexPath.row]
return valueAt1stCell
default:
//Second Array
let valueAt2ndCell = tableView.dequeueReusableCell(withIdentifier: "SecondCell", for: indexPath) as! SecondCustomTableviewCell
valueAt2ndCell.secondLabel.text = mutipleArrayForSecondCell[indexPath.row]
return valueAt2ndCell
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let valueAt1stCell = tableView.dequeueReusableCell(withIdentifier: "FirstCell", for: indexPath) as! multipleCustomCellTableViewCell
valueAt1stCell.Firstlabel.text = mutipleArrayForFirstCell[indexPath.row]
return valueAt1stCell
} else {
let valueAt2ndCell = tableView.dequeueReusableCell(withIdentifier: "SecondCell", for: indexPath) as! SecondCustomTableviewCell
valueAt2ndCell.secondLabel.text = mutipleArrayForSecondCell[indexPath.row]
return valueAt2ndCell
}
}
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
}
I am trying to use a UITableViewController(Static table view) with 4 sections and each has a different type of cell.
The number of cells in a section depends on the data received from the web service. In the storyboard, I have created one type of cell in each section.
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Number of rows in attachment sect
if section == 2 {
guard let currentDataModel = dataModel else { return 0 }
return currentDataModel.attachments.count
}
else if section == 3 {
guard let currentDataModel = dataModel else { return 0 }
return currentDataModel.contacts.count
}
return super.tableView(tableView, numberOfRowsInSection: section)
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let currentSection = indexPath.section
if currentSection == 2 {
let currentRow = indexPath.row
let cell = tableView.dequeueReusableCell(withIdentifier: "attachmentCell", for: indexPath) as! AttachmentViewCell
cell.setDataForCell(dataModel: dataModel?.attachments[currentRow], indexPath: indexPath)
return cell
}
//Show cells for Contact Section
else if currentSection == 3 {
let currentRow = indexPath.row
let cell = tableView.dequeueReusableCell(withIdentifier: "contactCell", for: indexPath) as! ContactViewCell
cell.setDataForCell(dataModel: dataModel?.contacts[currentRow], indexPath: indexPath)
return cell
}
return super.tableView(tableView, cellForRowAt: indexPath)
}
I am getting this error while calling dequeueReusableCellWithIdentifier:forIndexPath:
Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 2 beyond bounds [0 .. 1]'
Can I Use the different type of cells and a different number of rows in each section in a UITableViewController?
Can you try this.If need a four sections then return 4 in numberofsections. You can add the title to each sections as below and later add it to label in viewForHeaderInSection.You must provide the number of rows in each sections correctly.
override func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
return 4
}
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if(section == 0)
{
return "Section 0"
}
else if(section == 1)
{
return "Section 1"
}
else if(section == 2)
{
return "section 2"
}
else if(section == 3)
{
return "section 3"
}
return ""
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
switch(section)
{
case 0: //for first section
//return your count
case 1://Cells for
//return your count
case 2:
//return your count
case 3:
//return your count
default:
return 4
}
return 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath) as! Cell1
return cell
}
else if indexPath.section == 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath) as! Cell1
return cell
}
else if indexPath.section == 2 {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath) as! Cell1
return cell
}
else if indexPath.section == 3 {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath) as! Cell1
return cell
}
else {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath) as? Cell2
//Set up labels etc.
return cell!
}
}
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 50))
headerView.layer.borderWidth = 2
let myLabel = UILabel()
myLabel.frame = CGRectMake(0, 0, tableView.frame.width - 70, 50)
myLabel.font = UIFont.boldSystemFontOfSize(18)
myLabel.textColor = UIColor.whiteColor()
myLabel.textAlignment = .Left
myLabel.text = " " + self.tableView(tableView, titleForHeaderInSection: section)!
headerView.addSubview(myLabel)
return headerView
}
If you are using .xib file then you should also register that file in viewDidLoad() as
self.tableView.registerNib(UINib(nibName: "cell1", bundle: nil), forCellReuseIdentifier: "cell1")
self.tableView.registerNib(UINib(nibName: "cell2", bundle: nil), forCellReuseIdentifier: "cell2")