UICollectionViewCell's text is appearing somewhere else when the cell is reused - ios

I'm making a timetable app using swift.
I load my data from website and put it on a collectionView.
In the first section, I put the day of the week and in the first row, I put the classes and in other cells, I put the data from the web (subject Name, class room...)
If I enter the timetable view, everything is fine at first.
However, if I scroll down and scroll up, some text are printed where they shouldn't be.
This is my collectionView(collectionView: , cellForItemAtIndexPath: )
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
print("\(indexPath.section), \(indexPath.row)")
let dayArray = ["", "월", "화", "수", "목", "금"]
if indexPath.section == 0 {
// Day
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as UICollectionViewCell
var titleLabel = UILabel(frame: CGRectMake(0, 0, cell.bounds.width, cell.bounds.height))
cell.contentView.addSubview(titleLabel)
titleLabel.text = dayArray[indexPath.row]
titleLabel.textAlignment = NSTextAlignment.Center
cell.backgroundColor = mainColor
print("day")
return cell
}
if indexPath.row == 0 {
// index
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as UICollectionViewCell
var titleLabel = UILabel(frame: CGRectMake(0, 0, cell.bounds.width, cell.bounds.height))
cell.contentView.addSubview(titleLabel)
titleLabel.text = String(indexPath.section)
titleLabel.textAlignment = NSTextAlignment.Center
cell.backgroundColor = mainColor
print("time")
return cell
}
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! TimeTableCell
if let timeTableElement = self.timeTable[indexPath.section-1][indexPath.row-1] {
cell.subjectNameLabel.text = timeTableElement.subjectName
cell.subjectNameLabel.adjustsFontSizeToFitWidth = true
cell.classRoomLabel.text = timeTableElement.classRoom
cell.classRoomLabel.adjustsFontSizeToFitWidth = true
} else {
cell.subjectNameLabel.text = ""
cell.classRoomLabel.text = ""
}
cell.backgroundColor = mainColor
print("class")
return cell
}
I'm using a default UICollectionViewCell with adding a label subview to show the day and class time and using a custom TimeTableCell to show the class data.
How can I solve this problem?

Try to use a different 'reuseIdentifier' for TimeTableCell:
change reuse identifier in attributes inspector:
change your code:
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(yourReuseIdentifier, forIndexPath: indexPath) as! TimeTableCell
ps. I suggest to remove the existed titleLabel first and then add the new one, otherwise it will be add again when scrolling down and up.
EDIT
You can 'delete' the titleLabel in two ways:
add a custom cell as well as TimeTableCell(different name and different ReuseIdentifier). as you can see,subjectNameLabel in TimeTableCell will not be add again and again.
set a tag for titleLabel after initialization, and remove it according to the tag.
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as UICollectionViewCell
cell.contentView.viewWithTag(999)!.removeFromSuperview()
var titleLabel = UILabel(frame: CGRectMake(0, 0, cell.bounds.width, cell.bounds.height))
titleLabel.tag = 999
cell.contentView.addSubview(titleLabel)
titleLabel.text = dayArray[indexPath.row]
titleLabel.textAlignment = NSTextAlignment.Center
cell.backgroundColor = mainColor
print("day")
return cell

You need to Remove Title Label before you addd it
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as UICollectionViewCell
// Here find view with tag 999 and remove it from superview
var titleLabel = UILabel(frame: CGRectMake(0, 0, cell.bounds.width, cell.bounds.height))
cell.contentView.addSubview(titleLabel)
titleLabel.tag = 999;
titleLabel.text = String(indexPath.section)
titleLabel.textAlignment = NSTextAlignment.Center
cell.backgroundColor = mainColor
print("time")
return cell

Related

How does one prevent labels of different Swift cells displaying on top of each other?

Screenshot of the double text label
Current constraints of the label
Complete Hirearchy
What is my relevant code currently
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? ViewControllerTableViewCell {
let immy = cell.viewWithTag(1) as? UIImageView
let person: Userx = people[indexPath.row]
let text = person.Education
cell.lblName.text = person.Education. ///key line
cell.lblName.text = text?.uppercased()
cell.lblName?.layer.masksToBounds = true
let person5 = colorArray[indexPath.row]
let person6 = colorArray1[indexPath.row]
let person7 = colorArray2[indexPath.row]
let like = cell.viewWithTag(3) as? UIButton
cell.backgroundColor = person5
like?.backgroundColor = person6
immy?.backgroundColor = person7
cell.lblName.baselineAdjustment = .alignCenters
cell.postID = self.people[indexPath.row].postID
cell.row = indexPath.row
cell.delegate = self
cell.delegate2 = self
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
like?.isUserInteractionEnabled = true
}
return cell
}
return UITableViewCell()
}
What have I tried:
In prepare for reuse, I tried lblName.text = "" and lblName.text = nil Didn't work.
I also tried in cellForRowAt:
cell.lblName.text = nil
if cell.lblName.text == nil{
cell.lblName.text = person.Education
}
I also tried to get it done by constraints, no luck.
What I think might be cause
This didn't happen before I changed from TableViewController scene to ViewController(with an output table) scene.
It also didn't happen before I set the cells to have different colors.
I got it to work by checking clear graphics context on label2.
i think your problem would solve if you check cell heights ,
check heightForCellAtRow Func
I havent seen at your cell class. That issue happens when you have constraints issues. Since the autolayout system is unable to calculate the height of the row, the height becomes 0, any change from that point forward might be wrong.
I would suggest you check the cell code, add the labels to the contentView (if they are not) and add constraints between them:
eg:
bottomLabel.topAnchor.constraint(equalTo: topLabel.bottomAnchor, constant: 8).isActive = true
also set the compression resistance for both labels to be .defaultHigh and if you have the height of the row hardcoded remove that.

Swift: Using custom accessoryType for cell freezes UI and 99% CPU Usage

I'm trying to use a custom accessory type (UIImage) for my tableview cell which has a expand/collapse functionality. When user taps a cell the row expands or collpases if parent is tapped again.
The imageview I'm using to set the accessory type is below:
var expandIcon : UIImageView?
expandIcon = UIImageView(frame:CGRectMake(0, 0, 16, 16))
expandIcon!.image = UIImage(named:"expand")
Following code is when user taps a row which if its parent it should epxand or if its already expanded it will collapse.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellData = dataForCellAtRowIndex[indexPath.section]!.rows[indexPath.row]
var cell:UITableViewCell!
if isParentCell(indexPath.row) == true {
cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
cell.textLabel?.text = "test" + String(indexPath.row)
cell.detailTextLabel?.text = "detail"
cell.backgroundColor = UIColor.whiteColor()
cell.accessoryView = expandIcon
}else{
cell = tableView.dequeueReusableCellWithIdentifier("childCell", forIndexPath: indexPath)
cell.backgroundColor = UIColor.lightGrayColor()
cell.textLabel?.text = "child name"
cell.detailTextLabel?.text = "child detail"
cell.accessoryType = UITableViewCellAccessoryType.None
}
return cell
}
The bit that is causing the problem is cell.accessoryView = expandAccessory which causes the UI to freeze and cpu usage goes to 99% as reported by xcode. if i remove cell.accessoryView = expandIcon everything is fine! Why is this happening?
You should implement a function to return an expandIcon and then call it in place of expandIcon variable.
func expandImageView() -> UIImageView {
let expandIcon = UIImageView(frame:CGRectMake(0, 0, 16, 16))
expandIcon.image = UIImage(named:"expand")
return expandIcon
}
cell.accessoryView = expandImageView()
The fix for this as #rmaddy mentioned was the reuse of UIImage view which was causing the UI freeze. Creating a new UIImage for each cell fixed my problem so instead of:
if isParentCell(indexPath.row) == true {
cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
cell.textLabel?.text = "test" + String(indexPath.row)
cell.detailTextLabel?.text = "detail"
cell.backgroundColor = UIColor.whiteColor()
cell.accessoryView = expandIcon
}
i had to :
if isParentCell(indexPath.row) == true {
cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
cell.textLabel?.text = "test" + String(indexPath.row)
cell.detailTextLabel?.text = "detail"
cell.backgroundColor = UIColor.whiteColor()
//put the below two lines in a func and return a UIImage
let expandIcon = UIImageView(frame:CGRectMake(0, 0, 16, 16))
expandIcon.image = UIImage(named:"expand")
cell.accessoryView = expandIcon
}

How to make the tableview cell that has been selected to no color as Vine App

How to make the tableview cell that has been selected to no color as Vine App.
I've tried it but with clear color but the cell white out when it is get selected
Vine example no background color change
https://vid.me/tfkk
My project : Cell color changed even if it was set to clearColor
https://vid.me/awCq
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! DiscvoerTVC
let colorView = UIView()
colorView.backgroundColor = nil
UITableViewCell.appearance().selectedBackgroundView = colorView
if indexPath.row == 0 {
cell.DiscoverViewColor.backgroundColor = UIColor.grayColor()
cell.DiscoverViewLabel.text = "USMLE CK"
cell.backgroundColor = UIColor.grayColor()
cell.layer.cornerRadius = 20.0
cell.layer.masksToBounds = true
let colorView = UIView()
colorView.backgroundColor = nil
UITableViewCell.appearance().selectedBackgroundView = colorView
}
You mean cell's selection style? If so, set its selection style to none
cell.selectionStyle = .None;

ImageView in UITableViewCell won't display

I've put an ImageView in a UITableViewCell on my Storyboard but at run time it is not showing up on my simulator. How do I solve this?
My storyboard:
The object overview of my storyboard:
The Swift code that fills up the cells:
func tableView(gamesListTableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = gamesListTableView.dequeueReusableCellWithIdentifier("Game", forIndexPath: indexPath) as! UITableViewCell
if (indexPath.row < GamesList.count) {
cell.detailTextLabel?.text = GamesList[indexPath.row]["game_guid"].string!;
cell.textLabel?.text = GamesList[indexPath.row]["opponent_name"].string!;
if (GamesList[indexPath.row]["self_turn"] == false) {
cell.textLabel?.textColor = UIColor.greenColor();
} else if (GamesList[indexPath.row]["game_idle_time"] <= 60) {
cell.textLabel?.textColor = UIColor.yellowColor();
} else {
cell.textLabel?.textColor = UIColor.redColor();
}
} else {
cell.detailTextLabel?.text = InvitesList[indexPath.row - GamesList.count]["invite_guid"].string!;
cell.textLabel?.text = InvitesList[indexPath.row - GamesList.count]["invite_text"].string!;
cell.textLabel?.textColor = UIColor.blueColor();
}
return cell
}
What it looks like at runtime:
You should probably pause the execution and view your view hierarchy in Xcode. Check what the frame size it at run time and see if A.) something is overlapping it or B.)If your constraints are wrong.

Number cells for UITableView

I am trying number cell from 0-X for a uitableview. Currently I am using a label to do it and I just want the labels text to be 0,1,2,3,4,...X.
//label for the cell
let cellFrame: CGRect = CGRectMake(0, 0, 90, 32)
var cellLabel = UILabel(frame: cellFrame)
cellLabel.textAlignment = .Center
cellLabel.font = UIFont.MDFont.regularFourteen
cellLabel.text = ("\(indexPath.row)")
I have tried this approach and it just does 0,1,2,3,4 but when I scroll it prints 0,1,2,3,4 on top of the other numbers as well.
This is the whole code for the function
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier("cell") as! UITableViewCell
if cell == null {
//label for the cell
let cellFrame: CGRect = CGRectMake(0, 0, 90, 32)
var cellLabel = UILabel(frame: cellFrame)
cellLabel.textAlignment = .Center
cellLabel.font = UIFont.MDFont.regularFourteen
cellLabel.text = ("\(indexPath.row)")
cell.contentView.addSubview(cellLabel)
}
//print("Table data is \(tableData[5])")
return cell
}
I think there is issue related reusable cell. kindly try below code. may it help you.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier("cell") as! UITableViewCell
if cell == null {
//label for the cell
let cellFrame: CGRect = CGRectMake(0, 0, 90, 32)
var cellLabel = UILabel(frame: cellFrame)
cellLabel.textAlignment = .Center
cellLabel.font = UIFont.MDFont.regularFourteen
cellLabel.text = ("\(indexPath.row)")
cell.contentView.addSubview(cellLabel)
}
else {
for obj : AnyObject in cell.contentView.subviews {
if let label = obj as? UILabel {
label.text = ("\(indexPath.row)")
}
}
}
//print("Table data is \(tableData[5])")
return cell
}
Try this:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier("cell") as! UITableViewCell
if let cellLabel = cell.contentView.viewWithTag(10) as? UILabel {
cellLabel.text = ("\(indexPath.row)")
}
else {
let cellLabel = UILabel(frame: CGRectMake(0, 0, 90, 32))
cellLabel.tag = 10
cellLabel.textAlignment = .Center
cellLabel.font = UIFont.MDFont.regularFourteen
cellLabel.text = ("\(indexPath.row)")
cell.contentView.addSubview(cellLabel)
}
//print("Table data is \(tableData[5])")
return cell
}
When you compare variables you have to use nil.
Also in your case if the cell was nil, you should have created one. Because as you have it you try to add a label to a cell that doesn't exist.
See, when your table is loaded, your cells are nil for the visible region of screen... Here, its 4 cells, so your cell is nil condition will be satisfied for all 4 cells and you will get 4 cells having 0,1,2,3 text. But now when you scroll down, your cell will be reused and it wont go inside the condition so, it will show the old value that you've added in one of the above cells and hence will get wrong values.. You can use a simple approach:
Give tag (say, 1234) to your label when you allocate it when your cell is nil and access it outside the if condition, using that tag get that label and set text to it outside the if condition.. So, it will be called everytime and you will get 0,1,2,3,....X as you wanted...
Replace cellForRowAtIndexPath with this.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
var cell : UITableViewCell = UITableViewCell(frame: CGRectMake(0, 0, tableView.frame.size.width, 44))
let cellLabel = UILabel(frame: CGRectMake(0, 0, 90, 32))
cellLabel.tag = 10
cellLabel.textAlignment = .Center
cellLabel.text = ("\(indexPath.row)")
cell.addSubview(cellLabel)
return cell
}
Hope this helps you. :)
I think the problem is getting your row index using indexPath.row. Just create a local variable with the index thats added to the cell in the function cellForRowAtIndexPath() before the cell is returned. Then just reset the cellIndex=0 before calling reloadData(). I believe that would work
i.e
var cellIndex = 0
func ..cellForRowAtIndexPath ...()
{
//set the index to the cell label.
cell.label = cellIndex++
return cell
}

Resources