Search code examples
iosswiftuibezierpath

Сhange radius for UibezierPath swift


I drew an arc and added action to it. How can I use this action to change the radius of the arc ?? (Example: there was a radius of 30, clicked on the arc and +10. Clicked again and -10).I tried to change the radius but there was no result.While this does not move and I do not quite understand why this is so.

Here is the full class code.

@IBDesignable class circleView: UIView {

    typealias ArcAction = () -> Void

    struct ArcInfo {
        var outlinePath: UIBezierPath
        var action: ArcAction
    }

    private var arcInfos: [ArcInfo]!

    let bgShapeLayer = CAShapeLayer()
     var redRadius: Float?


    required init?(coder: NSCoder) {
        super.init(coder: coder)

        let recognizer = UITapGestureRecognizer(target: self, action: #selector(tap(_ :)))
        addGestureRecognizer(recognizer)
    }

    override func draw(_ rect: CGRect) {

        let fullCircle = CGFloat.pi * 2
        let arcAngle = fullCircle * 1.5 / 6

        var lastArcAngle = CGFloat.pi / 4.0 + CGFloat.pi //-CGFloat.pi

        arcInfos = []


     // Red Arc
        func redArc( action: @escaping ArcAction) {

            let path = UIBezierPath(arcCenter: CGPoint(x: rect.width/2, y: rect.height/2), radius: CGFloat(redRadius ?? 46), startAngle: lastArcAngle, endAngle: lastArcAngle + arcAngle, clockwise: true)

            #colorLiteral(red: 0.7450980392, green: 0.007843137255, blue: 0.262745098, alpha: 1).setStroke()
            path.lineWidth = 10
            path.stroke()
            lastArcAngle += arcAngle

            // separators
            #colorLiteral(red: 0.927436769, green: 0.9490308166, blue: 0.967099607, alpha: 1).setStroke()
            let outlinePath = hitTestPath(for: path)
            outlinePath.lineWidth = 3
            outlinePath.stroke()

            arcInfos.append(ArcInfo(outlinePath: outlinePath, action: action))
        }

        //Add Arc
        redArc {
            self.redRadius = 56

        }

    }

    @objc func tap(_ recognizer: UITapGestureRecognizer) {
        let location = recognizer.location(in: self)

        if let hitPath = (arcInfos.first { $0.outlinePath.contains(location) }) {
            hitPath.action()
            print(hitPath)
        }
    }

    func hitTestPath(for path: UIBezierPath) -> UIBezierPath {
        let pathCopy = path.cgPath.copy(strokingWithWidth: 15, lineCap: .butt, lineJoin: .miter, miterLimit: 0)
        return UIBezierPath(cgPath: pathCopy)
    }
}

Solution

  • You need to trigger a UI update...

        if let hitPath = (arcInfos.first { $0.outlinePath.contains(location) }) {
            hitPath.action()
    
            // add this line
            setNeedsDisplay()
    
            print(hitPath)
        }
    

    Note: your code as-is starts with a radius of 46... on tap, with that line added, it redraws itself with a radius of 56.