iosswiftuicontrol

How can I limit the range of motion on a custom UIControl Knob?


I'm following the tutorial here, which demonstrates how to implement a custom UIControl. However, I'd like to stop the custom control from spinning endlessly. I've been able to hinder the ability to spin the knob but have been unable to create a definite stopping point.

My Attempt

In the code below I'm using the authors angle variable which ranges from 0 to 360. The logic is a bit wonky, but I'm

 override func continueTrackingWithTouch(touch: UITouch, withEvent event: UIEvent?) -> Bool {
        super.continueTrackingWithTouch(touch, withEvent: event)

        if (angle <= 1) {
            angle = 2
            return false
        } else if angle >= 356 {
            angle = 355
            return false
        } else {
            let lastPoint = touch.locationInView(self)
            self.moveHandle(lastPoint)
            self.sendActionsForControlEvents(UIControlEvents.ValueChanged)

            return true
        }
    }

view code on github

note: I've tried all of the obvious operators and logic. I feel like this is the wrong approach entirely.

Result

Basically, the controls motion will stop at 1, but only if I'm moving slowly. If I quickly drag the knob, it'll spin right past the 1, allowing the control to spin endlessly.

Question

How can I properly limit the UIControls range of motion from 1 to 355?


I've put together a simple working project that you can download and test.

project files


Solution

  • Change continueTrackingWithTouch to:

    // Part of UIControl, used to track user input
    override func continueTrackingWithTouch(touch: UITouch, withEvent event: UIEvent?) -> Bool {
        let lastPoint = touch.locationInView(self)
        self.moveHandle(lastPoint)
    
        return super.continueTrackingWithTouch(touch, withEvent: event)
    }
    

    Change moveHandle to:

    func moveHandle(lastPoint:CGPoint){
        let threshholdAngle = 180
        let centerPoint:CGPoint  = CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2)
    
        let currentAngle:Double = AngleFromNorth(centerPoint, p2: lastPoint, flipped: false)
        let angleInt = Int(floor(currentAngle))
    
        let newAngle = Int(360 - angleInt)
        if abs(newAngle - angle) > threshholdAngle {
            return
        }
    
        //Store the new angle
        angle = newAngle
        sendActionsForControlEvents(UIControlEvents.ValueChanged)
    
        //Update the textfield
        //textField!.text = "\(angle)"
    
        //Redraw
        setNeedsDisplay()
    }