I have defined a class named c1 for a prototype cell like follows:
I defined the code for c1 like this:
class c1 : UITableViewCell {
public func configure(indexPath: IndexPath) -> UITableViewCell {
let place = places[indexPath.row]
self.textLabel?.text = place.name
self.detailTextLabel?.text = "\(place.timestamp)"
return self
}
}
Inside the UITableViewController following code:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell1", for: indexPath)
// Configure the cell...
return cell.configure(indexPath);
}
But this works not because obv. the compiler doesn't know about c1: "Value of type 'UITableViewCell' has no member 'configure'"
And I don't understand Why: If I specify the classname "c1" in the storyboard, I expected that XCODE instantiate the appear. class automatically for the reusing mechanism.
So the tableView method should return the runtime instantiated "c1" class which is an child of UITableViewCell to have access to the "configure" method?
just cast the cell to your specific cell
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell1", for: indexPath) as? c1
and the job is done
Must cast the type of UITableview cell
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell1", for: indexPath) as? c1 // to inherit the method of class c1, need to cast
// Configure the cell...
return cell.configure(indexPath);
}
Please ⌥-click on dequeueReusableCell or read the documentation
func dequeueReusableCell(withIdentifier identifier: String, for indexPath: IndexPath) -> UITableViewCell
returns the base class UITableViewCell
If you declare a custom (sub-)class you have to cast the cell to the subclass. By the way please name the class with a starting capital letter.
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell1", for: indexPath) as! c1
And in configure you might have to return Self or c1
public func configure(indexPath: IndexPath) -> Self {
let place = places[indexPath.row]
self.textLabel?.text = place.name
self.detailTextLabel?.text = "\(place.timestamp)"
return self
}
And where does places come from in the cell? The configure method seems to be pointless.
To access the methods of your UITableViewCell you will have to cast the cell to that particular UITableViewCell
i.e
let cell = tableView.dequeueReusableCell(withIdentifier: "YOUR_IDENTIFIER") as? YOUR_CELL_CLASS
In case if you have the multiple UITableViewCell so you have to assign then a different identifier so based on that you can identify the particular cell. More or less there should an awareness which display your cell based on your data.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let aCellType = aCellData[indexPath.row].cellType //aCellData is the predefined data
switch aCellType {
case c1:
let cell = tableView.dequeueReusableCell(withIdentifier: "YOUR_IDENTIFIER") as? YOUR_CELL_CLASS_C1
cell.YOUR_METHOD_OF_THIS_CELL()
return cell
case c2:
let cell = tableView.dequeueReusableCell(withIdentifier: "YOUR_IDENTIFIER") as? YOUR_CELL_CLASS_C2
cell.YOUR_METHOD_OF_THIS_CELL()
return cell
case c3:
let cell = tableView.dequeueReusableCell(withIdentifier: "YOUR_IDENTIFIER") as? YOUR_CELL_CLASS_C2
cell.YOUR_METHOD_OF_THIS_CELL()
return cell
default:
debugPrint("That's all folks")
}
return UITableViewCell()
}
Hope this helps you!
Related
I am making a form with a tableView with multiple kind of cell types. One of these types contains an UICollectionView with buttons to select some answers.
What I need is to be able to hide or show rows in the table, regarding on the answers.
For example: when answer to question 2 is "No", question 3 is not showing anymore.
But I don't know how to make that tableview knows what's being selected in one of it's cells
In the cell that contains the UICollectionView I have this method
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let indexPath = optionsCollectionView.indexPathsForSelectedItems?.first
let cell = collectionView.cellForItem(at: indexPath!) as! OptionsCollectionViewCell
let data = cell.itemButton.titleLabel?.text
selectedItem = data
}
But I don't know how to automatically pass it to the tableview so it knows what rows to show or hide... Any idea?
this is my cellForRowAt
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if sortedFixedContentType.count != 0 {
let item = sortedFixedContentType[indexPath.row]
switch item.typeId {
case "42":
let cell = tableView.dequeueReusableCell(withIdentifier: "FormFileCell", for: indexPath) as! FormFileCell
return cell;
case "39":
let cell = tableView.dequeueReusableCell(withIdentifier: "FormExpenseTypeCell", for: indexPath) as! FormExpenseTypeCell
return cell;
case "86":
let cell = tableView.dequeueReusableCell(withIdentifier: "FormExpensePaymentModeCell", for: indexPath) as! FormExpensePaymentModeCell
return cell;
case "87":
let cell = tableView.dequeueReusableCell(withIdentifier: "FormExpenseFileTypeCell", for: indexPath) as! FormExpenseFileTypeCell
return cell;
case "88":
let cell = tableView.dequeueReusableCell(withIdentifier: "FormProviderCell", for: indexPath) as! FormProviderCell
return cell;
default:
let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! BaseFormCell
cell.idLabel.text = item.htmlType
return cell
}
}
else {
let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! BaseFormCell
cell.idLabel.text = ""
return cell
}
}
Thanks
There are Four steps to do this :-
1.First create a protocol lets say 'CustomCellDelegate' in your custom cell where you are using collectionview inside and create a variable that will hold the custom delegate just to give a example suppose your cell name is CustomCell create a CustomCellDelegate and declare it as customDelegate
protocol CustomCellDelegate : class {
func Method1()
}
class CustomCell : UITableViewCell {
var customDelegate : CustomCellDelegate?
}
2.Then you need to fire that delegate from CustomCell class collectionview delegate method didSelectItemAt like this
extension CustomCell : UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if let delegate = customDelegate {
delegate.Method1()
}
}
}
3.Third assign the customDelegate to the view controller where you want to get the delegate for example myViewController here
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "customeCellIdentifier", for: indexPath) as! CustomCell
cell.customDelegate = self // myViewController
return cell
}
4.Handle the delegate in your view controller like this
extension myViewController : CustomCellDelegate {
func Method1() {
print("Method 1 called")
}
}
I Hope this will solve your problem let me know if you find this answer helpful. Cheers!!
When I'm compiling my app, I get a warning and I don't know how to fix or hide it. Conditional cast from UITableViewCell to UITableViewCell always succeeds
This is my part of the code, where the warning appears.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrayPDF.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "MyCellPDF", for: indexPath)
as? UITableViewCell else { return UITableViewCell() }
cell.textLabel?.text = arrayPDF[indexPath.row] + ".pdf"
return cell
}
This part of my code generates the warning.
as? UITableViewCell else { return UITableViewCell() }
Everything is working fine. I'm stuck.
Thanks in advance!
By default, tableView.dequeueReusableCell(withIdentifier: "MyCellPDF", for: indexPath) returns a UITableViewCell object.
So, when you do:
guard let cell = tableView.dequeueReusableCell(withIdentifier: "MyCellPDF", for: indexPath) as? UITableViewCell else { return UITableViewCell() }
You are casting an UITableViewCell object to an UITableViewCell. Xcode just tells you that is useless.
If your class is a UITableViewCell, you can just use:
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCellPDF", for: indexPath)
If it is a custom class, you can use the guard but replace the as? UITableViewCell part with as? MyCustomTableViewCellClass.
Regards,
IMACODE
You used guard .. else{},So it must optional,I guess the function you need is the first not the last:
open func dequeueReusableCell(withIdentifier identifier: String) -> UITableViewCell? // Used by the delegate to acquire an already allocated cell, in lieu of allocating a new one.
#available(iOS 6.0, *)
open func dequeueReusableCell(withIdentifier identifier: String, for indexPath: IndexPath) -> UITableViewCell // newer dequeue method guarantees a cell is returned and resized properly,
You can right with eigther one in this way:
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCellPDF", for: indexPath)
OR
guard let cell = tableView.dequeueReusableCell(withIdentifier: "MyCellPDF") else { return UITableViewCell() }
So I have this function.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier = "Cell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier) as! customCell
changeCellProperty(selectedIndexPath: indexPath)
return cell;
}
func changeCellProperty(selectedIndexPath: IndexPath){
print("indexpath = \(selectedIndexPath)") . // printing [0,0] and all values
let cell = self.tableView.cellForRow(at: selectedIndexPath) as! customCell
// got nil while unwrapping error in above statement.
cell.label.text = ""
// and change other properties of cell.
}
I am not able to understand the error.
When I am getting the indexpath, then why I am not able to point a particular cell and change properties accordingly.
You cannot access a cell that has not yet been added to the tableView. That is what you are trying to do here in changeCellProperty method. So, if your dequeue works, then all you would need to do is pass the dequeued cell to that method.
func changeCellProperty(cell: customCell){
cell.label.text = ""
// and change other properties of cell.
}
Your cellForRowAt method would look like this.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier = "Cell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier) as! customCell
changeCellProperty(cell: cell)
return cell
}
Note: class names should be UpperCamelCase. So your customCell should be named CustomCell.
I think I'm missing something fundamental to Swift, but can't find other examples of people doing what I'm trying:
Background
I have a UITableView with 2 prototype cells, with a different identifies, different features (label, image etc) and different classes.
I want the cellForRowAt function to return a different type and class of cell depending on the content in the array that holds the table data. That array is populated with struct instances, one characteristic of which identifies the type of cell that I want to represent the data.
Code Attempt
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch dataArray[indexPath.item].typeOfData {
case "Type1":
let cell = tableView.dequeueReusableCell(withIdentifier: "type1ReuseIdentifier", for: indexPath) as! type1Cell
//Set up the cell contents
return cell
case "Type2":
let cell = tableView.dequeueReusableCell(withIdentifier: "type2ReuseIdentifier", for: indexPath) as! type2Cell
//Set up the cell contents
return cell
default:
let cell = tableView.dequeueReusableCell(withIdentifier: "separatorIdentifier", for: indexPath) as! separatorCell
//Set up the cell contents
cell
}
}
What am I missing / doing wrong?
Edit:
It was missing the final return.
just do like this:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let typeSection = CellType(rawValue: indexPath.row)!
switch typeSection {
case .CenterTitleCell:
return getCenterTitleCell(tableView, indexPath)
case .CenterDescriptionCell:
return getCenterDescriptionCell(tableView, indexPath)
case .CenterImageCell:
return getImageCell(tableView, indexPath)
case .FooterTitleCell:
return getFooterViewCell(tableView, indexPath)
}
}
And use another method to return the Cell Type
func getCenterTitleCell (_ tableView: UITableView, _ indexPath:IndexPath) -> CenterTitleTableViewCell {
let cell:CenterTitleTableViewCell = tableView.dequeueReusableCell(withIdentifier: String(describing: CenterTitleTableViewCell.self),
for: indexPath) as! CenterTitleTableViewCell
cell.selectionStyle = .none
return cell
}
New to iOS programming, I am getting the following error, I get it for 3 separate items, but solving one will solve them all.
I am getting the following error
Value of type 'UITableViewCell' has no member 'postImageView'
// return how may records in a table
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.rssRecordList.count
}
// return cell
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> NewsTableViewCell {
// collect reusable cell
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
// find record for current cell
let thisRecord : RssRecord = self.rssRecordList[(indexPath as NSIndexPath).row]
// set value for main title and detail tect
cell.postImageView.image = UIImage(thisRecord.image)
cell.postTitleLabel.text = thisRecord.title
cell.authorLabel.text = thisRecord.storyDate
// return cell
return cell as! NewsTableViewCell
}
The problem is that your cell object is a UITableViewCell and not a NewsTableViewCell. You need to dequeue a NewsTableViewCell that will actually have those properties on it.
Something like:
var cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! NewsTableViewCell
try changing the following lines:
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! NewsTableViewCell
...
return cell
tableView.dequeueReusableCell returns a UITableViewCell which (as the compiler tells you) does not have the properties you are asking for.
You will have to cast it to the expected type NewsTableViewCell:
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! NewsTableViewCell