Predictive tableView swift 4 - ios

I have 2 tableView with 2 tableView first to display data & sec for predictive texts and I'm using textField as searchBar so when I set the cell for the sec tableView is give me that error when I try to return the cell at cellForRowAt method
Cannot convert return expression of type UITableViewCell.Type to return type UITableViewCell
and that's my code
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableView == tableView {
let cell = tableView.dequeueReusableCell(withIdentifier: "SearchCell", for: indexPath) as! searchCell
//cell.pics = receiveData[indexPath.item]
cell.titleCell.text = receiveData[indexPath.row].adeTitle
cell.cityCell.text = receiveData[indexPath.row].city
cell.dateCell.text = receiveData[indexPath.row].date
cell.distanceCell.text = receiveData[indexPath.row].distance
cell.priceCell.text = receiveData[indexPath.row].adePrice
if receiveData[indexPath.row].typ == "2" {
cell.kindCell.text = "used"
cell.kindCell.backgroundColor = UIColor.darkGray
cell.kindCell.textColor = UIColor.white
} else if receiveData[indexPath.row].typ == "1" {
cell.kindCell.text = "New"
} else {
cell.kindCell.text = "none"
cell.kindCell.backgroundColor = UIColor.darkGray
cell.kindCell.textColor = UIColor.white
}
} else {
var cell = searchTableView.dequeueReusableCell(withIdentifier: "Cell" )
if cell == nil {
cell = UITableViewCell(style: .default, reuseIdentifier: "Cell")
}
cell?.textLabel?.text = inputs[indexPath.row]
}
return UITableViewCell
}

Looks like UITableViewCell's instance is not returned in your cellForRowAt method,
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableView == tableView {
let cell = tableView.dequeueReusableCell(withIdentifier: "SearchCell", for: indexPath) as! searchCell
...
// do your stuffs with cell
...
return cell
}
return UITableViewCell()
}

Related

Dequeue multiple cells conforming to same protocol

I have a table view with 2 different cells. Both cells conform to same protocol "WorkoutCellProtocol" and I want to avoid rewriting same code during dequeuing. Probably there will more cells in the future, but each will conform to same protocol.
First cell is WorkoutCell with identifier: "WorkoutTableViewCell"
Second cell is CardioCell with identifier: "CardioTableViewCell"
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell: WorkoutCellProtocols!
cell.delegate = self
cell.editableRowBorders = colorEditable
cell.numberOfCell = indexPath.row
cell.numberOfExercise = indexPath.section
cell.configureTextFields(model:
exercises[indexPath.row])
if data[indexPath.row].category == "Cardio" {
cell = tableView.dequeueReusableCell(withIdentifier: "CardioTableViewCell", for: indexPath) as! CardioTableViewCell
return cell as! CardioTableViewCell
} else {
cell = tableView.dequeueReusableCell(withIdentifier: "WorkoutTableViewCell") as! WorkoutTableViewCell
return cell as! WorkoutTableViewCell
}
}
When I try to do this in this way, so assign properties only once at the top, before assigning a class types I get "Unexpectedly found nil while implicitly unwrapping an Optional value".
Dequeue your cell first, then configure it:
var cell: WorkoutCellProtocols
if data[indexPath.row].category == "Cardio" {
cell = tableView.dequeueReusableCell(withIdentifier: "CardioTableViewCell", for: indexPath) as! WorkoutCellProtocols
} else {
cell = tableView.dequeueReusableCell(withIdentifier: "WorkoutTableViewCell") as! WorkoutCellProtocols
}
cell.delegate = self
cell.editableRowBorders = colorEditable
cell.numberOfCell = indexPath.row
cell.numberOfExercise = indexPath.section
cell.configureTextFields(model: exercises[indexPath.row])
return cell
I'm assuming that your protocol is declared like this:
protocol WorkoutCellProtocols: UITableViewCell {
...
}
You can't do what you are trying to do with any implicitly unwrapped optional. Try moving the assignments down below the if block and type the cell to the protocol like this
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell: WorkoutCellProtocols!
if data[indexPath.row].category == "Cardio" {
cell = tableView.dequeueReusableCell(withIdentifier: "CardioTableViewCell", for: indexPath) as! CardioTableViewCell
} else {
cell = tableView.dequeueReusableCell(withIdentifier: "WorkoutTableViewCell") as! WorkoutTableViewCell
}
guard let workoutCell = cell as WorkoutCellProtocols! else { fatalError("Unexpected cell type") }
workoutCell.delegate = self
workoutCell.editableRowBorders = colorEditable
workoutCell.numberOfCell = indexPath.row
workoutCell.numberOfExercise = indexPath.section
workoutCell.configureTextFields(model: exercises[indexPath.row])
return workoutCell
}

Indexing Multiple Custom TableViewCell Xibs into TableView

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

How do I proceed on adding multiple prototype cell's

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

Multiple Tableviews inside Collection-view

I am working on Multiple Tableviews inside Collection-view. And I followed this article. But inside the cellForRowAt indexPath method I am getting following error.
Value of type 'UITableViewCell' has no member 'lblLab'
Value of type 'UITableViewCell' has no member 'lblLab'
Value of type 'UITableViewCell' has no member 'lblMedicine'
I have already created the separate classes for all the three tableview cells in which all the three labels are already mentioned.
Below is my code for the same which is written inside collection-view cell class.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell : UITableViewCell;
if tableView == tableLAB {
cell = tableView.dequeueReusableCell(withIdentifier: "labCell", for: indexPath) as! LabTableCell;
cell.lblLab!.text = arr1[indexPath.row];
} else if tableView == tableDIAGNOSIS {
cell = tableView.dequeueReusableCell(withIdentifier: "diagnosisCell", for: indexPath) as! DiagnosisTableCell;
cell.lblDiagnosis!.text = arr1[indexPath.row];
} else if tableView == tableMEDICINE {
cell = tableView.dequeueReusableCell(withIdentifier: "medicineCell", for: indexPath) as! MedicineTableCell;
cell.lblMedicine!.text = arr1[indexPath.row];
}
return cell;
}
can you tell me what I am doing wrong? Thanks in advance.
Problem is you are trying to force cast an object initialised through parent class into a child class, this is not possible, what you can do is make sure that you have conditional operators for all cases i.e
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if(tableview == a){
//This is a conditional statement
}
else if(tableview == b){
//This is a conditional statement
}
else{
//This is a conditional statement
}
//no need to return anything here as your conditional operators are handling all return //cases
}
and in each of the conditional statement, declare and initialise your unique cell type and return it eg.
let cell : CellType = tableView.dequeueReusableCell(withIdentifier: "CellType", for: indexPath) as! CellType;
return cell;
You can try
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableView == tableLAB {
let cell = tableView.dequeueReusableCell(withIdentifier: "labCell", for: indexPath) as! LabTableCell;
cell.lblLab!.text = arr1[indexPath.row];
return cell;
} else if tableView == tableDIAGNOSIS {
let cell = tableView.dequeueReusableCell(withIdentifier: "diagnosisCell", for: indexPath) as! DiagnosisTableCell;
cell.lblDiagnosis!.text = arr1[indexPath.row];
return cell;
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "medicineCell", for: indexPath) as! MedicineTableCell;
cell.lblMedicine!.text = arr1[indexPath.row];
return cell;
}
}

Using multiple UITableview in Single ViewController with Custom TableViewCell

How can I return a TableViewcell in cellForRowAtIndexPath delegate method , if I m using multiple UITableView in a Single ViewController, One TableView has Custom UITableViewCell and the other has default UITableViewCell . My problem is I m not able to cast the UITableViewCell to Custom TableViewCell type .
Code used as follows ,
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell?
if tableView == self.tvCity {
var cell:UITableViewCell?
cell = tableView.dequeueReusableCellWithIdentifier(cityCellIdentifier, forIndexPath: indexPath) as UITableViewCell
let row = indexPath.row
cell!.textLabel?.text = self.cityList[row].cityEn
}
if tableView == self.tvBranchByCity {
var cell:BranchNearMeTableViewCell?
cell = (tableView.dequeueReusableCellWithIdentifier(branchCellIdentifier, forIndexPath: indexPath) as! BranchNearMeTableViewCell)
let row = indexPath.row
cell.branchName = self.branchList[row].name// here cell.branchName is not accessible.
}
return cell!
}
Please advise . Thanks in advance.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if tableView == self.tvCity {
var cell:UITableViewCell?
cell = tableView.dequeueReusableCellWithIdentifier(cityCellIdentifier, forIndexPath: indexPath) as UITableViewCell
let row = indexPath.row
cell!.textLabel?.text = self.cityList[row].cityEn
return cell!
}
if tableView == self.tvBranchByCity {
var cell:BranchNearMeTableViewCell?
cell = (tableView.dequeueReusableCellWithIdentifier(branchCellIdentifier, forIndexPath: indexPath) as! BranchNearMeTableViewCell)
let row = indexPath.row
cell.branchName = self.branchList[row].name as! String // here cell.branchName is not accessible.
return cell!
}
}
Differentiate tables with tag
see example :
if tableView.tag == 2000
{
identifier = "First Table"
let cell = tableView.dequeueReusableCellWithIdentifier(identifier, forIndexPath: indexPath)
return cell
}
else
{
identifier = "Second Table"
let cell = tableView.dequeueReusableCellWithIdentifier(identifier, forIndexPath: indexPath)
return cell
}

Resources