Standard TableView Cell - label text overlaps with uiimage - ios

This is happening but I don't know why. It is a standard tableviewcell with a label and an image on it
Here is the code:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = patientsTableView.dequeueReusableCell(withIdentifier: "patientTableViewCell", for: indexPath)
let text = "Bob Marley"
cell.textLabel?.text = text
return cell
}

When I do not put an image view in the object inspector but like below, it solves the problem. I am not sure why though
cell.imageView?.image = UIImage(named: "patients")

Related

Selection of UITableViewCell Changes when Scroll down in Swift

I am using a UITableView and what I am doing is I am changing the color of the cell when I tap on the cell using didSelectRow function of UITableView at cellForRowAt. The thing which is bothering me is when I scroll down or scroll up, those cells whom I changed the color before were changed to other cells. Here is my code:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = myTableView.dequeueReusableCell(withIdentifier: "TasksTableViewCell") as! TasksTableViewCell
cell.backView.backgroundColor = .white
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = myTableView.cellForRow(at: indexPath) as! TasksTableViewCell
cell.backView.backgroundColor = UIColor(named: "primaryViewColor")
}
Does anyone knows why this happens? Does anyone has a solution that when only those cells changes color whom I tap on, and when I scroll down or move up only those cells have the other color?
cellForRowAt will be called every time that cell is displayed.
you need selected list to save selected index.
var listSelected: [Int] = []
and
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TasksTableViewCell") as! TasksTableViewCell
cell.backView.backgroundColor = listSelected.contains(indexPath.row) ? UIColor(named: "primaryViewColor") : .white
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if listSelected.contains(indexPath.row) {
listSelected = listSelected.filter{$0 != indexPath.row}
} else {
listSelected.append(indexPath.row)
}
tableView.reloadRows(at: [indexPath], with: .automatic)
}
I encountered do you see the problem many times. Even if using and iVar can solve the problem, You are mixing "Controller" logic and "Model" logic.
I usually prefer to move "selection" state inside the model.
Suppose You have a class "Contact" you use to fill cell data (usual MVC pattern)
I add:
class contact{
..
var selected = false
}
AND in TV delegation method I use to apply selection, OR better I use a custom selection method in a custom cell (for example to see a √ element in cell)
As a bonus multiple selection come for free, and you can also save current selections for next run :)
So as I understand you select a cell and after that other cells look like they are selected?
If so I think this is happening because you change the background color of the cell and tableViews and collectionViews are reusing the cells, basically keeping the background you changed behind.
TableViewCells are reused as soon as they leave the visible area.
This means that a cell whose background you have colored will be deleted from the view hierarchy as soon as it is scrolled up or down. If the corresponding row is scrolled in again, the function cellForRowAt is called again for this IndexPath and the cell gets a white background.
The easiest is to save the IndexPaths of the selected cells and check in the cellForRowAt function if the current cell has to be selected.
Add the following var to the viewController class:
var selectedIndexPaths = Set<IndexPath>()
and modify the tableView delegate methods:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = myTableView.dequeueReusableCell(withIdentifier: "TasksTableViewCell") as! TasksTableViewCell
cell.backView.backgroundColor = (selectedIndexPaths.contains(indexPath) ? UIColor(named: "primaryViewColor") : .white)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
if selectedIndexPaths.contains(indexPath)
{
selectedIndexPaths.remove(indexPath)
}
else
{
selectedIndexPaths.insert(indexPath)
}
tableView.reloadRows(at: [indexPath], with: .none)
}
You can use
step 1: create model
class DemoModel {
var isSelected: Bool = false
var color: UIColor = .While
}
step 2: and in tableview
var listDemo: [DemoModel] = [DemoModel(),...]
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = myTableView.dequeueReusableCell(withIdentifier:
"TasksTableViewCell") as! TasksTableViewCell
var obj = listDemo[indexPath.row]
cell.backView.backgroundColor = obj.color
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
var obj = listDemo[indexPath.row]
obj.color = UIColor(named: "primaryViewColor")
tableView.reloadRows(at: [indexPath], with: .automatic)
}

How reutilize the cells

My table have the functionality to delete a row, but when add a new row is writting two labels in the same place, a label above of the other label
a label belong to the deleted row and the other label belong to the new label when add a new row
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = UITableViewCell()
tableView.register(newCell.self, forCellReuseIdentifier:"newCell");
cell = tableView.dequeueReusableCell(withIdentifier: "newCell", for: indexPath) as! newCell
cell.textLabel.text= value
return cell
}
}
First of all, register your cell outside the cellForRowAt indexPath function, preferably where you are adding your tableView.
For this instance, register it in viewDidLoad
So
tableView.register(newCell.self, forCellReuseIdentifier:"newCell")
goes into viewDidLoad
for the function, try this:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "newCell", for: indexPath) as! newCell
cell.textLabel.text= value
return cell
}
Hope this helps. Also, provide more context to what is going wrong and what is the intended behaviour.

reloadData for UITableView changes constraints

I have a UITableView set up with cells: (no conflicting constraints)
Storyboard and Constraints
Looks like:
Pre-refresh
However, whenever I refresh using
self.tableView.reloadData()
the constraints seem to change which changes the cell into:
Post-refresh
Any suggestions as to why this happens?
Code for cellForRowAt:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CaptureCell
let capture = tabBar?.captureArray[indexPath.row]
cell.capsuleImage.image = capture?.image
return cell
}
The cell identifier is "cell" and I have CaptureCell which is a subclass of UITableViewCell.

iOS Swift - UITableViewCell with left detail and right detail and subtitle?

how to add a right detail to a cell that already have left detail and subtitle. and how to give a textLabel to the right detail?
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
let monster = monsters[indexPath.row]
cell.textLabel?.text = monster.name
cell.detailTextLabel?.text = monster.subtitle
return cell
}
Try this
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
let monster = monsters[indexPath.row]
cell.textLabel?.text = monster.name
cell.detailTextLabel?.text = monster.subtitle
let label = UILabel.init(frame: CGRect(x:0,y:0,width:100,height:20))
label.text = monster.name
cell.accessoryView = label
return cell
}
Click on your tableView cell. It's easier to do it in document outline.
Change the style attribute in Attribute Inspector from Basic to Custom. You will now be able to add a label. The basic template is set, so you can't alter it. I believe this was the issue you were having.
I'm sure after you place the label you know what to do, but just in case:
Place the new label at the right margin of the cell and pin it to the top, bottom, and right, using Autolayout.
Reconnect your title, subtitle IBOutlets, and create a right label IBOutlet, connect it, and you should be done.

how to change text size in tableView

Can anyone tell me how to change the text size in a tableView so that the text in the screenshot below fits within the width of the screen:
The current tableView code is:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
cell.textLabel!.text = self.dataArray[indexPath.row]
cell.imageView!.image = UIImage(named: "20x20_empty-round-radiobutton-choice-ui")
return cell
}
Thanks in advance!
Try the following code:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
cell.textLabel!.text = self.dataArray[indexPath.row]
cell.textLabel.font = UIFont(name: cell.textLabel.font.fontName, size:15) // Change the font size as per your requirement
cell.imageView!.image = UIImage(named: "20x20_empty-round-radiobutton-choice-ui")
return cell
}
Set autoshrink minimum fontScale. If your text is long enough to exceed the actual Label Frame,then your font will be shrinked upto minimum font scale you provide in storyboard or xib.

Resources