1

My app is written in Swift 2.0 and needs to run on iOS 8.1 or higher. I use Xcode 7.0.

I am using a standard UITableViewController. My UITableView has only one kind of custom prototype cells CustomCell that subclasses UITableViewCell. The CustomCell has a couple of UILabels inside, all of them have clear background colour and fixed width and height. Everything is laid out in the Interface Builder.

I receive data very often (10+ times/s) from another source. The labels in my cell have to update their content based on the received data. I also need to animate the labels backgrounds colours. To do this, I use the following:

extension UIView {   
    func fadeOut() {
        self.layer.backgroundColor = UIColor.blackColor().CGColor
        UIView.animateWithDuration(2.0, delay: 0.0, options: UIViewAnimationOptions.CurveEaseOut, animations: { () -> Void in
            self.layer.backgroundColor = UIColor.clearColor().CGColor
        }, completion: nil)
    }
}

I update the labels using the following code:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("customCell", forIndexPath: indexPath) as! CustomCell
    let oldText = customLabel.text
    let newText = dataForLabels[indexPath.row].custom
    if newText != oldText {
        cell.customLabel.fadeOut()
    }
    cell.customLabel.text = dataForLabels[indexPath.row].custom
    return cell
}

And my update (callback) method looks like this:

var dataForLabels:[Int:(custom: String?, anotherCustom: String?)] = [:]

func updateData(CustomData data) {
    for d in data {
        dataForLabels[d.index] = (custom: data.custom, anotherCustom: data.anotherCustom)
    }
    tableView.reloadData()
}

Now, the problem itself:

When there is no change in data for specific cell/label, the animation should go on (fading effect, 2s). When the data changes, the animation should restart.

When I call reloadData(), and there was no change of data, the animation is removed/stopped, that is, the label's background colour is suddenly clear with no fading effect.

I have tried dispatching reloadData() to the main thread, but it doesn't help. I have tried using CABasicAnimation instead of animateWithDuration(), but it doesn't solve the problem either.

I tried a similar scenario, but without using a table at all (just a couple of UIViews instead of cells) and it works. The problem is when I use reloadData().

I have tried debugging it, but I am not good when it comes to disassembly. I saw that layout_if_needed() was called and somewhere there all animations were removed.

What I suspect is that when reloadData() is called, the layout manager thinks that for some reason constraints changed and there is a need to update the layout, which breaks all animations.

Is there any solution to this problem, preferably one where I can keep using Interface Builder?

Any help will be greatly appreciated.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
pingd
  • 118
  • 11

1 Answers1

1

You do not need to reload the tableview if data on the labels change, just change the text on the labels. You need only to reload the tableview if e.g. the count of rows changes or you need to re-create the cells.

Just get the index paths of the visible rows with tableView.indexPathsForVisibleRows and iterate over the visible cells to change text or background.

Darko
  • 9,655
  • 9
  • 36
  • 48