I want to display comments without separator as the image below I tried using the separator but it didn't work I need separator only for the first cell.
super.viewDidLoad()
self.commentstableView.separatorColor = UIColor.clearColor()
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//post's section == 0
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCellWithIdentifier("postCID", forIndexPath: indexPath) as! postCell
self.commentstableView.separatorColor = UIColor.grayColor()
}
let cell = tableView.dequeueReusableCellWithIdentifier("commentCID", forIndexPath: indexPath) as! commentCell
// Configure the cell...
cell.textLabel?.text = comments[indexPath.row]
return cell
}
In StoryBoard, go to your postCell prototype and add a thin UIView and set its background color and height in the Attributes inspector.
But then...
Your logic is garbled and you're shadowing declarations of cell, so it will need to fit into the following structure:
(Edited)
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCellWithIdentifier("postCID", forIndexPath: indexPath) as! postCell
// Additional cell configuration
return cell
}
else {
let cell = tableView.dequeueReusableCellWithIdentifier("commentCID", forIndexPath: indexPath) as! commentCell
// Configure the cell...
cell.textLabel?.text = comments[indexPath.row]
return cell
}
}
You can add a grey view with 1 point height in your first custom cell, and in the rest of cells you don't need this view, and of curse you should hide the separator of the table view so you can show only your custom separator. I hope this helps.
Related
I have a tableview in my storyboard where the prototype cell has a disclosure indicator by default.
When I populate my table I want to remove the indicator only from the last cell AND center a spinner on it.
I'm doing it like this:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CharacterCell", for: indexPath) as! CharacterCell
if indexPath.row == charactersViewModel.charactersCount - 1 {
cell.accessoryType = .none
cell.accessoryView = .none
// Spinner
let spinner = UIActivityIndicatorView(style: .large)
spinner.color = .white
spinner.center = cell.contentView.center
cell.contentView.addSubview(spinner)
spinner.startAnimating()
}
return cell
}
The problem is that the spinner is offcenter, a little bit to the left, just like if the accessory is still there, but hidden.
I feel maybe I'm missing the lifecycle of a table cell, maybe it's getting the center value of the content view when the accessory is still there, so when it's removed it is offcenter?
I tried on willDisplay as well but the same thing happens.
Any tips on this?
As #Paulw11 mentioned, I used a second subclass and created another cell prototype in my tableview.
Then when the last position at the table is reached, we can use the second prototype on cellForRowAt.
Here how it is:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row >= charactersViewModel.charactersCount - 1 {
reloadRows(indexPath: indexPath)
let cell = tableView.dequeueReusableCell(withIdentifier: "LoadingCharacterCell", for: indexPath) as! LoadingCharacterCell
cell.startSpinner()
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "CharacterCell", for: indexPath) as! CharacterCell
cell.configureCell(charactersViewModel: charactersViewModel, cell: cell, index: indexPath.row)
return cell
}
}
private func reloadRows(indexPath: IndexPath) {
var indexPathList = [IndexPath]()
indexPathList.append(indexPath)
charactersTableView.reloadRows(at: indexPathList, with: .automatic)
}
And with the reloadRows function, the last cell is updated and removed when the table receives more data.
in an App I am writing, i have a form built using storyboard around a UITableView with static cells in a UITableViewController. The table has 6 rows that collects different bits of information. Row 0,3,4,5 have textfield/textview/labels to collect/display some information, row 1 has a UICollectionView with a dozen or so icons. row 2 has a height of 50 but is empty for now.
this setup works well but i am trying to add some functionality and i am stumped.
depending on what I select in the UICollectionView (in row 1), i would like to load one of a number of different cells in row 2
for example, if i click on the 2nd icon (blood pressure), the cell to load in row 2 will be used to input the systolic and diastolic values. if I click on the 3rd icon (temperature), the cell to load in row 2 will be used to input the temperature, etc...
i've designed the cells in separate class files of UITableViewCell and the corresponding xib files. i know how to register them using
tableView.register(UINib(nibName: "myBPTableCell", bundle: nil), forCellReuseIdentifier: "myBPTableCell")
just not sure where to put the logic to update the table on the fly.
if eventTypeCollectionIndex == 4 {
let cell = tableView.dequeueReusableCell(withIdentifier: "myBPTableCell", for: indexPath) as! myBPdTableCell
return cell
}
i was thinking in
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
but since this function has to return a cell, i am not sure how to return the pre-existing cells for anything other than row 2
thanks
Sami
You would want to define different cases in the cell for row at index method. And then when the user taps a button, reload the cell that you would want to change.
You would either use reload rows or self.tableView.reloadData()
So for example:
var didTap = false
func buttonTapped() {
didTap = true
// Reload table
}
And then either use a different nib for the cell:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if didTap {
// show new appearance
let cell = tableView.dequeueReusableCell(withIdentifier: "myBPTableCell", for: indexPath) as! myBPdTableCell
return cell
} else {
// show original
let cell2 = tableView.dequeueReusableCell(withIdentifier: "myBPTableCell2", for: indexPath) as! myBPdTableCell2
return cell2
}
}
Or you could update the properties of the same nib class:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "myBPTableCell", for: indexPath) as! myBPdTableCell
if didTap {
// show new appearance
cell.backgroundColor = .white
} else {
// show original
cell.backgroundColor = .black
}
return cell
}
Edit based on comment:
You can also just do the following, where you have one cell for row 2 and then another cell for the other rows:
if indexPath.row == 2 {
let cell = tableView.dequeueReusableCell(withIdentifier: "myBPTableCell", for: indexPath) as! myBPdTableCell
if didTap {
cell.backgroundColor = .white
} else {
cell.backgroundColor = .black
}
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "myOtherCell", for: indexPath) as! myOtherCell
return cell
}
I am trying to make a custom table view cell.
If I do this:
class TableViewCell: UITableViewCell {
#IBOutlet weak var cellBackgroundImage : UIImageView!
}
And:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! TableViewCell
cell.cellBackgroundImage.backgroundColor = UIColor.white
cell.cellBackgroundImage.layer.masksToBounds = false
cell.cellBackgroundImage.layer.cornerRadius = 5
let event = self.fetchedResultsController.object(at: indexPath)
self.configureCell(cell, withEvent: event)
return cell
}
I obtain a white rounded cell background. Easy. And I can use the original cell.textLabel.text.
Perfect.
But, if I want to do something more complex:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as? TableViewCell
if (cell == nil) {
cell = UITableViewCell(style: UITableViewCellStyle.subtitle, reuseIdentifier: "Cell") as? TableViewCell
cell?.cellBackgroundImage.backgroundColor = UIColor.white
cell?.cellBackgroundImage.layer.masksToBounds = false
cell?.cellBackgroundImage.layer.cornerRadius = 5
self.configureCell(cell!, withObject: object)
}
And at the same time to use the original table view properties as UITableViewCellStyle.subtitle and cell.accessoryView, the app crashes or shows the wrong output.
THIS MEANS THAT I MUST USE A FULL CUSTOM CELL WITH MORE OUTLETS TO REPLACE THE ORIGINAL ELEMENTS AS UITableViewCellStyle.subtitle and cell.accessoryView ???
I will express it in a different way:
Can I use a custom tableview cell only for one purpose (like the rounded background) and use the original elements such as the subtitle style and the accesory view?
In afirmative case, how?
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellReuseIdentifier") as! CustomTableViewCell
let text = data[indexPath.row]
cell.label.text = text
return cell
}
above on is the code that I saw to follow.
my code is as below
I don't know why it getting nil value on
tableView.dequeueReusableCell(withIdentifier: "locCell")
my storyboard is as below
I added identifier like below(you can see it on bottom-right section of pic
You need to register the cell for reuse.
tableView.register(LocationTableCell.self, forCellReuseIdentifier: "locCell")
Or enter your reuse identifier in the storyboard by selecting your cell and then entering the reuse identifier in the properties to the right.
Simply because tableView.dequeueReusableCell(withIdentifier: "cell") by default is nil.
It is the same case for any optional when trying to print it out, example:
let optionalString: String? = ""
print(optionalString)
leads to get:
So, by declaring a constant as:
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
since dequeueReusableCell(withIdentifier:) returns an optional UITableViewCell instance, the type of cell would be UITableViewCell? (optional UITableViewCell), that's why you are seeing this error.
How to get rid of it?
Assuming that you have set the cell right identifier for your cell:
Well, in case of having your custom cell, you could cast it as:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as? MyCustomCell else {
// something goes wrong
return UITableViewCell()
}
print(cell) // it would be fine for now
// ...
return cell
}
And if you don't have a custom cell, all you have to do is to remove the as? MyCustomCell down casting.
Replace
let cell = tableView.dequeueReusableCell(withIdentifier: "locCell")
With this code:
let cell = tableView.dequeueReusableCell(withIdentifier: "locCell", for: indexPath)
func tableView (_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "cellReuseIdentifier", for: indexPath) as! CustomTableViewCell
cell.label.text = data[indexPath.row].name
return cell
}
NOTE: In your storyboard set tableView Delegate, DataSource and set cell ID cellReuseIdentifier.
I am trying to implement a custom table view which has different types of cells: type A and type B. All of my cells should be of type A, except for one that will be of type B. Whenever the users selects a cell, this one changes to type B.
My code is the following one:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let row = indexPath.row
if (row == typeBCellIndex) {
// Get Type B cell
let cell = tableView.dequeueReusableCellWithIdentifier(typeBCellIdentifier, forIndexPath: indexPath) as! TypeBTableViewCell
return cell
} else {
// Get Type A cell
let cell = tableView.dequeueReusableCellWithIdentifier(typeACellIdentifier, forIndexPath: indexPath) as! TypeATableViewCell
cell.detailLabel.text = "I am a type A cell"
return cell
}
}
The variable typeBCellIndex is initialised in 0, and this code gives an error when I add a new cell and try to dequeue the cell at index 1.
In Objective-C, as this links indicates, I would check if the cell is nil, and if not create a new instance of the corresponding cell. However, I am not sure if this concept applies to Swift, and in case it does, I don't know how to do it.
declare a variable cellindex before viewdidload method and initialize to 3 or any number
and in tableview design two different cells and assign unique identifier for each
code for tableview is
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell : UITableViewCell!
var row = indexPath.row
if(row == cellindex){
cell = tableView.dequeueReusableCellWithIdentifier("Cell2", forIndexPath: indexPath) as! UITableViewCell
}else{
cell = tableView.dequeueReusableCellWithIdentifier("Cell1", forIndexPath: indexPath) as! UITableViewCell
}
return cell
}
the cellindex row will be cell2 and other cells are cell1