I have two tableviews with two different custom tableview cells.. and am doing this:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableView == self.tableview {
let cell = tableview.dequeueReusableCell(withIdentifier: "matchescell") as! MatchesTableViewCell
// ......
return cell
} else {
let cell = tableview.dequeueReusableCell(withIdentifier: "filtercell") as! FilterTableViewCell
// ......
return cell
}
}
and of course i have registered them both from storyboard...
but i keep getting this:
on this line:
let cell = tableview.dequeueReusableCell(withIdentifier: "filtercell") as! FilterTableViewCell
tried to register them like this:
tableview.register(MatchesTableViewCell.self, forCellReuseIdentifier: "matchescell")
filterdrop.register(FilterTableViewCell.self, forCellReuseIdentifier: "filtercell")
but still getting the same error!
What am doing wrong?!
The problem is that you typed "tableview" instead of "tableView" in your else part:
replace :
let cell = tableview.dequeueReusableCell(withIdentifier: "filtercell") as! FilterTableViewCell
with :
let cell = tableView.dequeueReusableCell(withIdentifier: "filtercell") as! FilterTableViewCell
It is crashing because your "tableview" doesn't have this cell registered.
Add the "filtercell" identifier in the storyboard or xib custom cell (FilterTableViewCell).
Possible cause:
You haven't registered the class or the nib of the cell to the proper tableview
You haven't set the identifier in the cellview in you nib/storyboard
You have inverted the tableview and their cell type
This because you either didn't register the cell
tableView.register(CustomCellClass.self, forCellReuseIdentifier: "CellID")
//
tableView.register(UINib(nibName: "CustomCellClass", bundle: nil), forCellReuseIdentifier: "CellID")
or you swapped the dequeuing line for the tables
Have a look into your Tableview controller in the Storyboard. You should have another indentier than called in:
let cell = tableview.dequeueReusableCell(withIdentifier: "filtercell") as! FilterTableViewCell
BTW, you should always use this newer function
dequeueReusableCell(withIdentifier:for:)
instead of
dequeueReusableCell(withIdentifier:)
See this post for details.
You can easily solve this problem just to check what tableview you use at that time.
you can try this code,
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) {
if (tableview == (yourtableview 1)) {
let cell = yourtableview 1.dequeueReusableCell(withIdentifier: "yourtableview Cell 1") as? yourtableview Cell 1
// write your code for tableview 1
return cell
}
else
{
let cell = yourtableview 2.dequeueReusableCell(withIdentifier: "yourtableview Cell 2") as? yourtableview Cell 2
// write your code for tableview 2
return cell
}
}
Related
I have a table view that has several sections, two sections are almost identical but their header names are different. so I have one registered nib and I'm using it in two rows:
self.tableView.register(UINib(nibName: "ImprestDetailInfoHeaderTableViewCell", bundle: nil), forCellReuseIdentifier: "PaymentsReceiptsDetailsHeader")
and In my cellforrowat for table view I have this:
case 2:
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "PaymentsReceiptsDetailsHeader", for: indexPath) as! ImprestDetailInfoHeaderTableViewCell
cell.selectionStyle = .none
cell.headerType = ImprestDetailInfoType.payment
cell.checkedAndTotalNumber = self.imprestViewModel.getStringCheckedAndTotalNumberOfPayments()
self.paymentHeaderDelegate = cell
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "AddImprestPaymentsReceiptsDetailTableView", for: indexPath) as! ImprestReceiptPaymentDetailTableViewCell
cell.imprestItems = self.imprestViewModel.getPaymentsImprestItems()
cell.delegate = self.imprestViewModel
return cell
}
case 3:
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "PaymentsReceiptsDetailsHeader", for: indexPath) as! ImprestDetailInfoHeaderTableViewCell
cell.selectionStyle = .none
cell.headerType = ImprestDetailInfoType.receipt
cell.checkedAndTotalNumber = self.imprestViewModel.getStringCheckedAndTotalNumberOfReceipts()
self.receiptHeaderDelegate = cell
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "AddImprestPaymentsReceiptsDetailTableView", for: indexPath) as! ImprestReceiptPaymentDetailTableViewCell
cell.imprestItems = self.imprestViewModel.getReceiptsImprestItems()
cell.delegate = self.imprestViewModel
return cell
}
as you see first row of 2nd and 3rd sections have identical definitions. when I click on either of these rows, I need them to show their detailed information and I change an image icons on headers, but this seems to be have a conflicting behaviour, so when I click on first row, this changes icons of both and similar strange things. Is there any chance that this problem be cus of that two cells use same nib identifier?
cus I checked my delegates and I found no problem there, the only thing I can think is some bug in swift memory management for these situations.
UPD: didSelectRowAtIndexPath:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.section == 1 {
self.delegate?.summartySectionDidTapped()
} else if indexPath.section == 2 && indexPath.row == 0 {
self.paymentsDetailIsOn.toggle()
self.paymentHeaderDelegate?.detailHeaderSelected()
} else if indexPath.section == 3 && indexPath.row == 0 {
self.receiptsDetailIsOn.toggle()
self.receiptHeaderDelegate?.detailHeaderSelected()
}
}
I changed
self.tableView.register(UINib(nibName: "ImprestDetailInfoHeaderTableViewCell", bundle: nil), forCellReuseIdentifier: "PaymentsReceiptsDetailsHeader")
to
self.tableView.register(UINib(nibName: "ImprestDetailInfoHeaderTableViewCell", bundle: nil), forCellReuseIdentifier: "PaymentsDetailsHeader")
self.tableView.register(UINib(nibName: "ImprestDetailInfoHeaderTableViewCell", bundle: nil), forCellReuseIdentifier: "ReceiptsDetailsHeader")
and it seems that the problem fixed!!! (different ids for different cells)
If you want to insert an header in sections you can use the function func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
Is more simple to implement the tableView as you want
Hey guys befor you mark this as a duplicate just please hear me out. I have tried everything related to this topic including adding
self.tableView.registerClass(UserCell.self, forCellReuseIdentifier: "cell")
I have also changed my placeholder cell to match the UserCell class
Im Not sure what it could be! I get the error :
Could not cast value of type 'UITableViewCell' (0x1134700e0) to 'Lightning_Chat.UserCell'
with type SIGBRT not sure what could be going on and ive tried everything please help!
here is table view code :
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
// not casting for some reason
let cell : UserCell = UITableViewCell(style: .subtitle , reuseIdentifier: "cellId") as! UserCell
cell.textLabel?.text = contacts[indexPath.row].userName
cell.detailTextLabel?.text = contacts[indexPath.row].score
if let profileImageUrl = contacts[indexPath.row].picURL {
let url = URL(string: profileImageUrl)
URLSession.shared.dataTask(with: url!, completionHandler: { (data, response, error) in
//download hit an error
if error != nil {
print(error!)
return
}
DispatchQueue.main.async {
cell.profileImageView.image = UIImage(data: data!)
}
}).resume()
}
return cell;
}
here is my view did load :
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.register(UserCell.self, forCellReuseIdentifier: "cellId")
//irrelevant
fetchUsers()
}
Instead of:
let cell : UserCell = UITableViewCell(style: .subtitle , reuseIdentifier: "cellId") as! UserCell
Try this:
let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! UserCell
You are not creating the cell correctly.
Change:
let cell : UserCell = UITableViewCell(style: .subtitle , reuseIdentifier: "cellId") as! UserCell
to:
let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! UserCell
Note that your code is directly creating a UITableViewCell which is why you can't cast it. You are bypassing the standard cell reuse as well.
Here are the step to fix your problem
Change your table view content to be dynamic cell, instead of static cell
Maintain the code on your viewDidLoad function self.tableView.register(UserCell.self, forCellReuseIdentifier: "cellId"). Also don't forget to connect table view delegate and datasource
On your table view cellForRowAt index path method, don't instantiate the cell directly. Instead use let cell = self.tableView.dequeueReusableCell(withIdentifier: cellIdentifier)!;
Basically that error you got, is because of mix and match the wrong properties on your table view.
Hope it helps
I never get this print . it is like is always nil, doesnt matter how much i scroll it up or down :/
if let update = tableView.cellForRow(at: indexPath ) as? RestCell {
print("VISIBLE CELL")
}
Complete code..
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell : RestCell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! RestCell
// Pass data to Cell :) clean the mess at the View Controller ;)
cell.restData = items[indexPath.row]
// Send cell so it can check update the image to the right cell ;)
// cell.cell = tableView.cellForRow(at: indexPath ) as? RestCell
//print("LA CELDA ES \(tableView.cellForRow(at: indexPath ))")
if let update = tableView.cellForRow(at: indexPath ) as? RestCell {
print("VISIBLE CELL")
}
return cell
}
You have not returned your cell from cellForRow method so this is the reason why your if statement is returning false. I'm not sure why you are trying to do this but there have to be a better way. If you want to look for visible cells you can use UITableView visibleCells variable.
In my app I am using a custom tableViewCell using a xib file. I create the .xib file outlet the labels etc to my TableViewCell class
In my ViewController the code I used to populate and show the cell on the table view is as follows:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let transaction = statementArray[indexPath.row]
let cell = Bundle.main.loadNibNamed("StatementCell", owner: self, options: nil)?.first as! StatementCell
cell.transAmount.text = String(transaction.transAmount)
cell.transDesc.text = transaction.transDesc
cell.transFees.text = String(transaction.transFees)
return cell
}
I am aware that the way tableViews work is that they reuse the cell that goes off the screen. Is the way i am loading the .xib and populating the cell correct? Or do I have to add something to my code?
First you need to register your custom cell with UITableView
yourTableView.register(UINib(nibName: "StatementCell", bundle: nil), forCellReuseIdentifier: "cellIdentifier")
then in UITableView Delegate method cellForRowAt you need to write
let cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier", for: indexPath) as! StatementCell
cell.textLabel?.text = "Sample Project"
return cell
now you can access your UITableViewCell properties with cell.propertyName
and you must take care that "cellIdentifier" and "forCellReuseIdentifier" both value must be same.
One more thing is you need to register your class for reuse identifier in viewDidLoad method.
YourTable.registerclass(tablecell, forCellReuseIdentifier: "identifier"
And make sure you have connect all the required outlets.
FIrst Register Custom cell nibCalss in tableview
let str1 : NSString = "StatementCell"
tableView.register(UINib(nibName: "StatementCell", bundle: nil), forCellReuseIdentifier: str1 as String)
Now initialise tableviewcell
let cell1:StatementCell = tableView.dequeueReusableCell(withIdentifier: str1 as String) as! StatementCell!
Now access tableviewcell outlet collection.
I have currently have two UITableViews populated with contacts for the app. I have one for simply viewing them and editing/deleting and one for searching/picking contacts from a list. However, I'm getting a returned nil value when trying to use the same custom class cell for both UITableViews.
These are my two cellForRowAtIndexPath functions.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("SecondCell") as! ContactCell
let item = contacts[indexPath.row]
cell.meetupLabel?.text = item.fullName
return cell
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("FirstCell") as! ContactCell
let item = contacts[indexPath.row]
cell.label?.text = item.fullName
return cell
}
If the table did not have a cell named FirstCell or SecondCell, the dequeueReusableCellWithIdentifier(_:) method will return nil, and you will need to construct the cell yourself.
// no don't do this.
let cell: ContactCell
if let c = tableView.dequeueReusableCell(withIdentifier: "FirstCell") as? ContactCell {
cell = c
} else {
cell = ContactCell(style: .default, reuseIdentifier: "FirstCell")
}
You should use dequeueReusableCell(withIdentifier:for:), which was introduced in iOS 6, if you would like UIKit to construct the cell for you:
// swift 3
let cell = tableView.dequeueReusableCell(withIdentifier: "FirstCell",
for: indexPath) as! ContactCell
// swift 2
let cell = tableView.dequeueReusableCellWithIdentifier("FirstCell",
forIndexPath: indexPath) as! ContactCell
...
Also, check if you have given the correct reuse-identifiers to the cells correctly in the interface builder.
As you said you are getting nil, my quick guess is that you haven't registered the cell at some point, runs earlier than this cell event. Look at this thread on how to register cell.