简体   繁体   中英

Some tableview cell content disappears after scroll (swift)

Below is my custom cell class:

class AthleteTableViewCell: UITableViewCell {

var myLabel1: UILabel!
var myLabel2: UILabel!
var profile: UIImageView!
var star = StarButton()
var touched = false

required init(coder aDecoder: NSCoder) {
    fatalError("init(coder:)")
}

override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)

    let gap : CGFloat = 10
    let labelHeight: CGFloat = 30
    let labelWidth: CGFloat = 150
    let lineGap : CGFloat = 5
    let label2Y : CGFloat = gap + labelHeight + lineGap


    myLabel1 = UILabel()
    myLabel1.frame = CGRect(x: gap, y: gap, width: labelWidth, height: labelHeight)
    myLabel1.textColor = UIColor.black
    contentView.addSubview(myLabel1)

    myLabel2 = UILabel()
    myLabel2.frame = CGRect(x: gap * 5, y: label2Y, width: labelHeight, height: labelHeight)
    myLabel2.textColor = UIColor.white
    myLabel2.textAlignment = .center
    myLabel2.backgroundColor = UIColor.flatMint()
    myLabel2.layer.cornerRadius = 15.0
    myLabel2.clipsToBounds = true
    contentView.addSubview(myLabel2)

    profile = UIImageView()
    profile.image = UIImage()
    profile.frame = CGRect(x: bounds.width - gap, y: bounds.height / 2, width: bounds.height * 1.25, height: bounds.height * 1.25)
    profile.layer.cornerRadius = (bounds.height * 1.25) / 2
    profile.layer.masksToBounds = true
    contentView.addSubview(profile)

    if (touched != false) {
        star.isSelected = true
        star.frame = CGRect(x: gap, y: label2Y, width: labelHeight, height: labelHeight)
        contentView.addSubview(star)
    } else {
        star.frame = CGRect(x: gap, y: label2Y, width: labelHeight, height: labelHeight)
        contentView.addSubview(star)
        star.isEnabled = true
    }
}

}

and below is the method for creating my cells:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = AthleteTableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "myCell")

    cell.myLabel1.text = "\(myArray[indexPath.row])"
    cell.myLabel1.textColor = UIColor.white
    cell.myLabel2.isHidden = true

    cell.profile.image = UIImage(named: cell.myLabel1.text!)

    cellArray.append(cell)

    if (cell.touched) {
        cell.star.isSelected = true
    } else {
        cell.star.isOpaque = true
    }

    cell.backgroundColor = UIColor(white: 1, alpha: 0.2)

    return cell
}

and below is the method for selecting a cell which trips an animation that I would like the final state of to persist on the tableview cell.

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    makeSelection(tableView, didSelectRowAt: indexPath)
}

func makeSelection(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let cell = tableView.cellForRow(at: indexPath) as! AthleteTableViewCell
    cell.selectionStyle = UITableViewCellSelectionStyle.none

    if(selectionArray.contains(myArray.object(at: indexPath.row))) {
        //Popping selection off of the stack and updating all labels
        updateLabels(tableView: tableView)
        selectionArray.remove(myArray[indexPath.row])
        cell.star.isFavorite = false
        cell.myLabel2?.isHidden = true
        //need to somehow implement all of the rank labels decreasing by one if I deselect someone
        cell.touched = false
        //updateLabels(tableView: tableView)
    } else {
        selectionArray.add(myArray[indexPath.row])
        cell.touched = true
        let rank = selectionArray.count
        cell.myLabel2.isHidden = false
        cell.myLabel2?.text = "\(rank)"
        cell.star.isFavorite = true
    }
}

This is a photo of what a cell looks like when you select it:

在此处输入图片说明

and this is a photo of that same cell after scrolling down so that is out of view and then scrolling back:

在此处输入图片说明

Something clearly goes very wrong here - I added that "touched" boolean to the custom table view cell class under the assumption that maybe the cells were being redrawn and there was no way for it to know whether it should have that star animated or not so it was considered nil but that fix doesn't seem to work (maybe I am onto something but implemented it incorrectly?)

Let me know if you have any clue what is going on here! thanks so much!!!

Your code has a variety of problems. In your tableView(_:cellForRowAt:) method, you should be calling dequeueReusableCell(withIdentifier:for:) .

You should not be trying to read data from the cells in order to load content. You should save state data to a data model of some sort. An array works well for a table view with a single section, and an array of arrays works well for a sectioned table view.

There are countless tutorials on how to use table views. You need to go do some reading.

Mentioning it as an answer here as a step by step process

1) Create Struct for your data

struct Profile {
var personName: String?
var photoURL: String?
var rank: String?
var isTouched: Bool?

// add init method and stuff
}

2) Populate your array using these Profile elements. So that in the end you have an array of profiles.

3) Use this array to populate your tableview with each cell element getting data from the Profile object.

4) in your cellForRowAt method use dequeueReusableCell(withIdentifier:for:) to initialize your cell and assign values

5) if for that particular profile, isTouched is true then show

cell.star.isFavorite = true

else set it to false

6) in your didSelectRow, get indexpath.row and then in your array of profiles set Profile.isTouched=true/false based on your needs for that particular row and toggle accordingly. Update your profile array with new profile object.

7) refresh tableview.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM