Interactive Tracking with iOS Charts. How to

I figured it out to save you sometime

enter image description here

extension GraphViewController: ChartViewDelegate {

    func chartValueSelected(_ chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) {

        // I used the x pixel property of the highlight to update the
        // position of the floating label, and set its text to the 
        // x value of the selected entry
        floatingLabelCenterConstraint?.constant = highlight.xPx
        floatingLabel.text = "  Mar 14  \(highlight.x)"

        // Create the nice transition animation
        // fadeIn() and fadeOut() are simple extension methods I wrote
        if floatingLabel.isHidden {
            floatingLabel.fadeIn()
            subscripts.fadeOut()
        }

        // This gives you the y value of the selected entry
        greenNumber.text = NSString(format: "%.2f", highlight.y) as String
    }
}

However, this delegate method is called only when you are moving your finger. You need a way to tell when the pan gesture ended. Charts does not have this delegate method out of the box, so you need to add it. Go to the ChartViewBase.swift source file, add the following to ChartViewDelegate protocol

public protocol ChartViewDelegate
{
    ...
    @objc optional func panGestureEnded(_ chartView: ChartViewBase)
}

Then go to BarLineChartViewBase.swift, find panGestureRecognized function

@objc private func panGestureRecognized(_ recognizer: NSUIPanGestureRecognizer)
{
    ...
    else if recognizer.state == NSUIGestureRecognizerState.ended || recognizer.state == NSUIGestureRecognizerState.cancelled
    {
    ...

    // Add this line at the end
    delegate?.panGestureEnded?(self)
    }
}

Finally, go back to your viewController and add the following. Now everything works like a charm

func panGestureEnded(_ chartView: ChartViewBase) {
    subscripts.fadeIn()
    floatingLabel.fadeOut()

    // clear selection by setting highlightValue to nil
    chartView.highlightValue(nil)
}

UPDATE

This feature has now been added to the latest version of IOS-Charts via this pull request.

ChartViewDelegate was updated to now include the following method.

public protocol ChartViewDelegate
{
     ...

    /// Called when a user stop highlighting values while panning
    @objc optional func chartViewDidEndPanning(_ chartView: ChartViewBase)
} 

All you have to do is implement that method wherever you're implementing ChartViewDelegate (the viewController with your chart).

Original Answer Sub-Class LineChartView

@JGuo's answer works, but it requires you to change code inside the pod. These means that every time you update your pod(s) you'll have to re-implement these changes. You can achieve the same results without modifying the pod as follows:

Create a protocol

import Charts

@objc protocol MyChartViewDelegate {
    @objc optional func chartValueNoLongerSelected(_ chartView: MyLineChartView)
}

SubClass LineChartView

open class MyLineChartView: LineChartView {

    @objc weak var myChartViewDelegate: MyChartViewDelegate?

    private var touchesMoved = false

    // Haptic Feedback
    private let impactGenerator = UIImpactFeedbackGenerator(style: .light)
    private let selectionGenerator = UISelectionFeedbackGenerator()

    override open func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        // This is here to prevent the UITapGesture from blocking touches moved from firing
        if gestureRecognizer.isKind(of: NSUITapGestureRecognizer.classForCoder()){
            return false
        }
        return super.gestureRecognizerShouldBegin(gestureRecognizer)
    }

    override open func nsuiTouchesBegan(_ touches: Set<NSUITouch>, withEvent event: NSUIEvent?) {
        impactGenerator.impactOccurred()
        selectionGenerator.prepare()
        // adds the highlight to the graph when tapped
        super.nsuiTouchesBegan(touches, withEvent: event)
        touchesMoved = false
        if let touch = touches.first {
            let h = getHighlightByTouchPoint(touch.location(in: self))

            if h === nil || h == self.lastHighlighted {
                lastHighlighted = nil
                highlightValue(nil, callDelegate: true)
            }
            else {
                lastHighlighted = h
                highlightValue(h, callDelegate: true)
            }
        }
    }

    open override func nsuiTouchesEnded(_ touches: Set<NSUITouch>, withEvent event: NSUIEvent?) {
        super.nsuiTouchesEnded(touches, withEvent: event)
        myChartViewDelegate?.chartValueNoLongerSelected?(self) // remove the highlight
    }

    open override func nsuiTouchesCancelled(_ touches: Set<NSUITouch>?, withEvent event: NSUIEvent?) {
        super.nsuiTouchesCancelled(touches, withEvent: event)
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
            // if a tap turns into a panGesture touches cancelled is called this prevents the highlight from being moved
            if !self.touchesMoved {
                self.myChartViewDelegate?.chartValueNoLongerSelected?(self)
            }
        }
    }

    override open func nsuiTouchesMoved(_ touches: Set<NSUITouch>, withEvent event: NSUIEvent?) {
        super.nsuiTouchesMoved(touches, withEvent: event)
        touchesMoved = true

        if let touch = touches.first {
            let h = getHighlightByTouchPoint(touch.location(in: self))

            if h === nil {
                lastHighlighted = nil
                highlightValue(nil, callDelegate: true)
            }
            else if h == self.lastHighlighted {
                return
            }
            else {
                lastHighlighted = h
                highlightValue(h, callDelegate: true)
                selectionGenerator.selectionChanged()
            }
        }
    }
}

Create your Chart

let lineChartView = MyLineChartView()

override func viewDidLoad() {
    super.viewDidLoad()
    lineChartView.delegate = self // built in delegate for user interaction
    lineChartView.myChartViewDelegate = self // delegate with our additions (knowing when a value is no longer selected)
    lineChartView.highlightPerTapEnabled = false // disable tap gesture to highlight
    lineChartView.highlightPerDragEnabled = false // disable pan gesture
}

Implement Delegates

extension MyViewController: ChartViewDelegate {

    func chartValueSelected(_ chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) {
        // Do something on selection
    }

}

extension MyViewController: MyChartViewDelegate {

    func chartValueNoLongerSelected(_ chartView: FlyLineChartView) {
        // Do something on deselection
    }
}