I am trying to use a three tableviews in a XIB. I've created a custom UITableViewCell class, however when I am trying to use it, comes up with an error saying..."Unexpectedly found nil while unwrapping an Optional value". I have tried regist
internal func tableView(_ tableView: UITableView, cellForRowAt
indexPath: IndexPath) -> UITableViewCell{
if tableView == resultsTable {
if savedWheelsArray.count > 0 {
self.resultsTable.register(accessoryCellTableViewCell.self, forCellReuseIdentifier: "accessoryCell")
let cell = tableView.dequeueReusableCell(withIdentifier: "accessoryCell" , for: indexPath) as! accessoryCellTableViewCell
//let wheel = savedWheelsArray[indexPath.row]
cell.AccessoryTitle.text = "WTF"
cell.AcessoryImage.image = UIImage(named: "history")
print("set up searched wheels cell")
return cell
}
else {
let cellIdentifier : String = "accessoryCell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! accessoryCellTableViewCell
cell.AccessoryTitle.text = "no saved wheels"
cell.AcessoryImage.image = UIImage(named: "history")
print("no saved wheels found")
return cell
}
}
else {
}
return UITableViewCell()
}
Related
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
}
I have to show a couple of different cells. I called tableView(_:cellForRowAt:) for that, and in the method I use two different IDs for different classes of UITableViceCell
Here is a simple code:
class SimpleView: UITableViewController {
...
let cellIdMain = "JournalMainCellID"
let cellIdExtra = "JournalMainSceneAddNewID"
...
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == journals.count {
guard let cellAdding = tableView.dequeueReusableCell(withIdentifier: cellIdExtra, for: indexPath) as? JournalMainSceneAddNew else {
fatalError("Cannot connect to the cell")
}
return cellAdding
}
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdMain, for: indexPath) as? JournalMainSceneCell else {
fatalError("Cannot connect to the cell")
}
cell.numberOfCountriesLabel.text = "\(journals[indexPath.row].numberOFCountries)"
return cell
}
}
When I tried to find memory leaks I found:
When I click on the details I found:
Why this happened? It looks pretty simple and straightforward.
Updated: pictures were updated.
you are writing if conditions which will work only in one case as indexpath.row will only be equal to count
even though it will not work because after going through if it will execute block of code after if
which means your if block is waste
and why are you using cell.delegate??
Update your code with the following code.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == journals.count {
let cellAdding: JournalMainSceneAddNew = {
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdExtra) as? JournalMainSceneAddNew else {
return JournalMainSceneAddNew(style: UITableViewCellStyle.value1, reuseIdentifier: cellIdExtra)
}
return cell
}()
return cellAdding
}
let cell: JournalMainSceneCell = {
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdMain) as? JournalMainSceneCell else {
return JournalMainSceneCell(style: UITableViewCellStyle.value1, reuseIdentifier: cellIdMain)
}
return cell
}()
cell.numberOfCountriesLabel.text = "\(journals[indexPath.row].numberOFCountries)"
return cell
}
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()
}
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 have some custom UITableViewCell,and would using some of them randomly. But after I register them ,it will crashed in tableView(_cellForRowAt:).
Here is my code:
in viewDidLoad method
tableView.register(CustomACell.self, forCellReuseIdentifier: "Identifier")
tableView.register(CustomACell.self, forCellReuseIdentifier: "Identifier")
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let model = dataSource[indexPath.row]
if let type = model.type {
switch type {
case .A:
let cell = tableView.dequeueReusableCell(withIdentifier: MyIdentifier) as! CustomACell
cell.assgin(message: model)
return cell
case .B:
let cell = tableView.dequeueReusableCell(withIdentifier: MyIdentifier) as! CustomBCell
cell.assgin(message: model)
return cell
}
}
let cell = tableView.dequeueReusableCell(withIdentifier: MyIdentifier) as! CustomACell
cell.assgin(message: model)
return cell
}
If I register both ,it will crashed at case .A. If I won't, some of them would crash at tableView.dequeueReusableCell.
Here is one of the console error info:
Could not cast value of type 'TM.CustomACell' (0x10bb40940) to 'TM.CustomBCell' (0x10bb40578).
Change the CellReuseIdentifiers. You use same for both custom cells. Use diffrent identifires for diffrent cells.
var nibName = UINib(nibName: "Identifier1", bundle: nil)
self.tableView.register(nibName, forCellReuseIdentifier: "Identifier")
nibName = UINib(nibName: "Identifier2", bundle: nil)
self.tableView.register(nibName, forCellReuseIdentifier: "Identifier2")
Then change the cellForRowAt, try following code
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let model = dataSource[indexPath.row]
if let type = model.type {
switch type {
case .A:
let cell = tableView.dequeueReusableCell(withIdentifier: "Identifier1") as! CustomACell
cell.assgin(message: model)
return cell
case .B:
let cell = tableView.dequeueReusableCell(withIdentifier: "Identifier2") as! CustomBCell
cell.assgin(message: model)
return cell
default :
let cell = tableView.dequeueReusableCell(withIdentifier: "Identifier1") as! CustomACell
cell.assgin(message: model)
return cell
}
}
}
if you created a separate Nib, then you can register else no need to register
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) ->UITableViewCell{
var cell = UITableViewCell(style: .default, reuseIdentifier: "pgIdentifier")
if (XXX == true) {
let pgtcell = tableView.dequeueReusableCell(withIdentifier: "indetifier", for: indexPath) as! CustomCell1
} else {
let pgtcell = tableView.dequeueReusableCell(withIdentifier: "indetifier", for: indexPath) as! MyCustomCell1
}
}