0

This is killing me.. (.mov from my issue)

I'd like to position my custom view inside my custom tableViewCell. Made this simple expression for positioning: If : indexpath.row % 2 == 0 ---> set view on the left (like x: 10, y: 10) else: to the right.

When the app launches, all the bubbles are exactly below each other. When I scroll down to the end, it repositions itself. Not all of them, but some of them.

I started my code, and haven't finished with that though , because of this tiny little thing. My code below:

TableViewController

class QuestionsTableViewController: UITableViewController {

    let c = "cell"
    var users = [User]()

    override func viewDidLoad() {
        super.viewDidLoad()
        for i in 0..<6 {
        let user = User(firstName: "\(i) Karl", lastName: "May")
            users.append(user)
        }
    }
    // MARK: - Table view data source

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return users.count ?? 0
    }


    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> QuestionTableViewCell {

        let cell = tableView.dequeueReusableCellWithIdentifier(c, forIndexPath: indexPath) as! QuestionTableViewCell

          if indexPath.row % 2 == 0 {
        cell.bubleView.frame.origin =  CGPoint(x: origin.x + 10, y: origin.y + 10)
        cell.bubleView.backgroundColor = UIColor.blueColor()
    } else {
        cell.bubleView.frame.origin =  CGPoint(x: origin.x + 50, y: origin.y + 10)
        cell.bubleView.backgroundColor = UIColor.greenColor()
    }
        // Configure the cell...
        cell.nameLabel.text = users[indexPath.row].firstName + " " + users[indexPath.row].lastName

        return cell
    }
}

TableViewCell

class QuestionTableViewCell: UITableViewCell {

    @IBOutlet weak var bubleView: UIView!
    @IBOutlet weak var nameLabel: UILabel!

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

    func positionBuble() {
        bubleView.frame.origin = CGPoint(x: contentView.frame.origin.y+10, y: contentView.frame.origin.y+10)
    }
}

As far as I know, this code supposed to work, right? Am I missing something on Xcode Utilites pane? I use Xcode 7.1.1

screenshot from tableview

Zsolt
  • 49
  • 8
  • One thing that would possiby help, is the fact that from the looks of it, you are never "un calling" the bubble frame to reset in the UITableViewCell, and since you are using Reused cells, you must reset the cells to whatever state you consider, "normal state" so that the cells realign to where you want the, otherwise the cells will retain the value of the previous cell who occupied their memory slot – Larry Pickles Nov 30 '15 at 20:02
  • You can call to "-(void)prepareForReuse {} in a custom UITableViewCell swift file, obviiously translating the "void" to swift language, but you get the idea. subclassing a UITableViewCell allows you to place your normalization code into the overriden "prepareForReuse" method to then reset the cells each time the tableView passes data from the datasource to the cells in view. – Larry Pickles Nov 30 '15 at 20:04
  • This will only solve on part of your headache. the other part of the Cells all showing from the get go as being pegged to the left or right, I'd have to mess around with your code to see what we can force out of it, and I dont' have time for that, so take a look at preparing cells for reuse and see what you find out. This should solve the problem of the cells being stuck on the left or right when it should be pegged to be either right or left. Your if/then statement in cellforRowAtIndexPath doesn't have an "else" where you call to unset the View for the the TableViewCell, .. so – Larry Pickles Nov 30 '15 at 20:05
  • ... continued from above .. so you can either reset the view in PrepareForReuse or just complete the "else" statement in "cellForRowAtIndexPath" and you will win either way. The Else statement should counter the if statment by resetting the view to the left or right side depending on your modulo 2 checker in the if clause. Using the "else" clause will then allow you TO NOT have to use PrepareForReuse since the setting of the view will happen in the Else statement and reset for each cell that passes thorugh the cellforRowAtIndexPath. This is a side effect you are seeing from Reuse. – Larry Pickles Nov 30 '15 at 20:07
  • Thanks, but I started with that: "I started my code, and haven't finished with that though". And I tried it **first**, then post my question here. No result – Zsolt Nov 30 '15 at 20:15

2 Answers2

4

The problem is that you are missing the else:

    if indexPath.row % 2 == 0 {
        let origin = cell.bounds.origin
        //cell.positionBuble()
        cell.bubleView.frame.origin =  CGPoint(x: origin.x + 10, y: origin.y + 10)
        cell.bubleView.backgroundColor = UIColor.blueColor()
    } else {
        // what????
    }

You need this because cells are reused. A cell where indexPath.row % 2 == 0 will be used again where indexPath.row % 2 != 0, but you are not making any change, so they will all end up looking the same.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • yep, do this what Matt shows here, this is what I'm talking about for the most part, and this will get you probably all the way to the answer you need for your tableview – Larry Pickles Nov 30 '15 at 20:16
  • Really appreciate your code, but my initial was (with no effect, so removed it): if indexPath.row % 2 == 0 { cell.bubleView.frame.origin = CGPoint(x: origin.x + 10, y: origin.y + 10) cell.bubleView.backgroundColor = UIColor.blueColor() } else { cell.bubleView.frame.origin = CGPoint(x: origin.x + 50, y: origin.y + 10) cell.bubleView.backgroundColor = UIColor.greenColor() } LINK: https://www.dropbox.com/sh/cyqjqafw2jxz7bw/AAAMilpQkZ2CRbbB6JBA1owsa?dl=0&preview=scroll.mov – Zsolt Nov 30 '15 at 20:19
0

So, after numerous tries, I've created an other prototype cell, in which I set the design elements and runtime attributes, then called the new cell's identifier. Although, still don't know why my other approach did not work out...

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> QuestionTableViewCell {
        var cella: QuestionTableViewCell!

        if indexPath.row % 2 == 0 { //c is an identifier String
            let cell = tableView.dequeueReusableCellWithIdentifier(c, forIndexPath: indexPath) as! QuestionTableViewCell
            cella = cell
        } else { //b is also
            let cell = tableView.dequeueReusableCellWithIdentifier(b, forIndexPath: indexPath) as! QuestionTableViewCell
            cella = cell
        }
        // Configure the cell...
        cella.nameLabel.text = users[indexPath.row].firstName + " " + users[indexPath.row].lastName
        //cella.tralala.blabla = ...other properties
        return cella
    }
Zsolt
  • 49
  • 8