Search code examples
iosswiftuikit

Does iOS/UIKit have built in support for scheduling scroll like dinging


I want to implement an action that when I press and hold begins to repeatedly do an action (similar to a scroll button on a Desktop UI). Is there first class support for this in the UIGestureRecognizer/events framework, or do I just roll my own?

E.g.

var timer:Timer?

func killDing() {
    self.timer?.invalidate()
    self.timer = nil
}

func startDing() {
    self.killTimer()
    self.timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) {
        self.ding() // this is where the repeated code happens
    }
}

override func beginTracking(_ touch:UITouch, with event:UIEvent?) -> Bool {
    self.startDing()
}

override func endTracking(_ touch: UITouch?, with event: UIEvent?) {
    super.endTracking(touch, with: event)
    self.killDing()
}

I can of course do this with a LongPressGestureRecognizer as well. My question is whether I need to roll my own ding loop as shown above, or if there's something more first class in UIKit that I'm currently not aware of and should be taking advantage of.


Solution

  • I think you are on the right way. You can use use timers to repeat some actions, but you should add the created timer into a run loop with a common mode, without this mode, the run loop will not call the timer's action while a user is touching the screen

    let timer = Timer(timerInterval: interval, repeats: true, block: block) 
    RunLoop.current.add(timer, forMode: . common)
    

    Also you can use CADisplayLink, to call your action. You can find example of using CADisplayLink in my library, witch can help to you implement animation based on CADisplayLink:

    let link = CADisplayLink(target: self, selector: #selector(updateAction(sender:)));
    link.add(to: RunLoop.main, forMode: .commonModes);