UITableView, auto locate back at indexPath when user drags it I have a tableView, which auto locates back at indexPath after user has dragged it.

In other words, bouncing the tableView back into its bounds, after user dragged it out.

Here is the code:

// ...

var tracking = false
var currentPath = 0

@objc func updateRecorder(_ timer: Timer){
     currentPath = somethingCalculated
}

// ...

extension ViewController: UITableViewDelegate{


    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
            // when the scene is in a special state
            tracking = true
        }
    }

    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        // when the scene is in the same special state
        if tracking == true{
            tracking = false
            scrollToRow(at: IndexPath(row: currentPath, section: 0), at: UITableView.ScrollPosition.middle, animated: true)
        }
    }
}


In fact, it is a music tracking app. People sing a song, the lyric tableView tracks the voice, and it auto scrolls to current line.

When tracking, and people scrolls by hand, the lyric tableView should bounces back to it ought to be.

The code above works.

Any other ideas?
A couple of observations:


You are handling scrollViewDidEndDecelerating. But what if there was no deceleration? E.g. you’d generally want to call some common routine, e.g. didFinishUserScroll, either way:

func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
    if !decelerate {
        didFinishUserScroll()
    }
}

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
    didFinishUserScroll()
}

It looks like you are scrolling as soon as deceleration finishes. I would suggest that you only want to scroll at the end of the user gesture (whether decelerating or not) only if there is an update to the position in the lyrics in the intervening period of time.

E.g. you’re bopping along in a song, the drummer goes off into some lengthy, lyric-free solo, so the bored user starts scrolling through the lyrics themselves. When they let go, if the drum solo is still in progress, I’d suggest that you might not want to scroll back until the singing resumes. I wouldn’t necessarily scroll back immediately.

Now maybe you’ve got the sort of logic in the code you didn’t share with us, and if so, don’t worry about it. But, frankly, the fact that tracking is so ambiguous is code smell. (I.e., is it a boolean whether a touch gesture is in progress? is it indicating that we’re following along with lyrics at all? is it that there are updates to progress in the song that requires update of the position?) The fact that the intent of tracking is so ambiguous suggests you might consider a better name for it.
It looks like currentPath is an Int, a row number. So I wouldn’t call it currentPath, but rather currentRow.
When you have a boolean, you generally just check the value, not compare it to another boolean. So, for example, instead of:

if tracking == true {
    tracking = false
    scrollToRow(at: IndexPath(row: currentPath, section: 0), at: UITableView.ScrollPosition.middle, animated: true)
}


You would do:

if tracking {
    tracking = false
    scrollToRow(at: IndexPath(row: currentPath, section: 0), at: .middle, animated: true)
}


I also removed the redundant UITableView.ScrollPosition reference.
This is beyond the scope of this question, but the fact that you’re calling scrollToRow(at:at:animated:) without referencing the table view worries me, making me wonder whether you have all of this business logic buried inside your table view. We generally strive to isolate our UI from business logic of the app.