7.9 C
London
Friday, November 17, 2023

ios – Updating a UIView with a subview’s gesture handler


I’ve a easy app with a single ViewController containing a really minimal view hierarchy: DrawingView (a subclass of UIView), and three ImageViews (that are every youngsters of DrawingView).

Inside DrawingView, I’ve overridden draw(_:) to provide graphics which rely on the middle of every ImageView (particularly, a polygon whose vertices are the picture facilities). In the meantime, the ImageView positions are managed by the person by way of drag gestures. The gesture dealing with motion is a technique of ViewController.

I might like for DrawingView to replace in real-time because the ImageView positions change. To perform this, I’ve referred to as DrawingView.setNeedsDisplay() contained in the gesture handler. Nonetheless, this method solely updates DrawingView discretely, and seemingly not till the following gesture begins (no matter the place the decision seems within the change gesture.state assertion).

simulator screengrab

My query: the place/how ought to I name setNeedsDisplay to be able to obtain a clean (and real-time) replace to DrawingView? Or is there a greater method?

Listed below are my class definitions:

class ViewController: UIViewController {
    
    @IBOutlet var drawingView: DrawingView!

    @IBOutlet var majorVertex1: UIImageView!
    @IBOutlet var majorVertex2: UIImageView!
    @IBOutlet var majorVertex3: UIImageView!
    
    var majorVertices: [UIImageView]!
    
    @IBOutlet var majorVertex1XConstraint: NSLayoutConstraint!
    @IBOutlet var majorVertex1YConstraint: NSLayoutConstraint!
    @IBOutlet var majorVertex2XConstraint: NSLayoutConstraint!
    @IBOutlet var majorVertex2YConstraint: NSLayoutConstraint!
    @IBOutlet var majorVertex3XConstraint: NSLayoutConstraint!
    @IBOutlet var majorVertex3YConstraint: NSLayoutConstraint!
    
    var majorVertexXConstraints: [NSLayoutConstraint]!
    var majorVertexYConstraints: [NSLayoutConstraint]!
    
    static var majorVertexXOffsets: [Double]?
    static var majorVertexYOffsets: [Double]?
        
    override func viewDidLoad() {
        
        tremendous.viewDidLoad()
        
        majorVertices = [majorVertex1, majorVertex2, majorVertex3]
        majorVertexXConstraints = [majorVertex1XConstraint, majorVertex2XConstraint, majorVertex3XConstraint]
        majorVertexYConstraints = [majorVertex1YConstraint, majorVertex2YConstraint, majorVertex3YConstraint]
        ViewController.majorVertexXOffsets = majorVertexXConstraints.map {(constraint) -> Double in return constraint.fixed}
        ViewController.majorVertexYOffsets = majorVertexYConstraints.map {(constraint) -> Double in return constraint.fixed}
        
    }

    @IBAction func handlePan(_ gesture: UIPanGestureRecognizer) {
        
        guard let majorVertices = majorVertices,
              let gestureView = gesture.view
        else {return}
        
        guard let parentView = gestureView.superview,
              let gestureViewIndex = majorVertices.firstIndex(of: gestureView as! UIImageView)
        else {return}
        
        let translation = gesture.translation(in: parentView)
        
        change gesture.state {
            
        case .started:
            ViewController.majorVertexXOffsets = majorVertexXConstraints.map {(constraint) -> Double in return constraint.fixed}
            ViewController.majorVertexYOffsets = majorVertexYConstraints.map {(constraint) -> Double in return constraint.fixed}
            break
            
        case .modified:
            majorVertexXConstraints[gestureViewIndex].fixed = ViewController.majorVertexXOffsets![gestureViewIndex] + translation.x
            majorVertexYConstraints[gestureViewIndex].fixed = ViewController.majorVertexYOffsets![gestureViewIndex] + translation.y
            drawingView.setNeedsDisplay()
            break
            
        case .ended, .cancelled:
            majorVertexXConstraints[gestureViewIndex].fixed = gestureView.middle.x - parentView.body.measurement.width / 2.0
            majorVertexYConstraints[gestureViewIndex].fixed = gestureView.middle.y - parentView.body.measurement.top / 2.0
            break

        default:
            break
            
        }
        
    }

}


class DrawingView: UIView {
    
    override init(body: CGRect) {
        tremendous.init(body: body)
        setupView()
    }
    
    required init?(coder aDecoder: NSCoder) {
        tremendous.init(coder: aDecoder)
        setupView()
    }
    
    func setupView() {
        backgroundColor = .clear
    }
        
    override func draw(_ rect: CGRect) {
        tremendous.draw(rect)
        drawTriangle(rect)
    }
    
    inside func drawTriangle(_ rect: CGRect) {
        
        guard let context = UIGraphicsGetCurrentContext(),
              let majorVertexXOffsets = ViewController.majorVertexXOffsets,
              let majorVertexYOffsets = ViewController.majorVertexYOffsets
        else {return}
        
        let majorVertexXCenters = majorVertexXOffsets.map {(x) -> Double in return x + rect.width / 2.0}
        let majorVertexYCenters = majorVertexYOffsets.map {(y) -> Double in return y + rect.top / 2.0}
                
        context.setStrokeColor(UIColor.lightGray.cgColor)
        context.setLineWidth(3)
        
        context.transfer(to: CGPoint(x: majorVertexXCenters[0], y: majorVertexYCenters[0]))
        context.addLine(to: CGPoint(x: majorVertexXCenters[1], y: majorVertexYCenters[1]))
        context.addLine(to: CGPoint(x: majorVertexXCenters[2], y: majorVertexYCenters[2]))
        context.addLine(to: CGPoint(x: majorVertexXCenters[0], y: majorVertexYCenters[0]))
        
        context.strokePath()
        
    }
    
}

Latest news
Related news

LEAVE A REPLY

Please enter your comment!
Please enter your name here