Search code examples
iosswiftuiscrollviewcore-animationcalayer

Swift: How to enable pinch-to-zoom for CALayer?


I have been trying to scroll and zoom a CALayer, specifically a CAShapeLayer, of several polygon paths. I added the CALayer to a UIScrollView which has successfully enabled scrolling around the CALayer.

However, pinch to zoom is not working. Several tutorials have implemented zooming a UIImageView with the UIScrollViewDelegate essentially like so:

@IBOutlet var scrollView : UIScrollView!
var imageView = UIImageView()
scrollView.addSubview(imageView)

func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
    return imageView
}

But CALayer is incompatible with UIView and I have found no information on reconciling the difference.

Is there a similar native way to zoom a CALayer in Swift? Is it something really simple that escaped me? Any help would be appreciated; apologies if I am missing the obvious.


Solution

  • After much digging I found the related documentation from Apple. Turns out pinch-to-zoom is handled automatically on CALayers if they are set up correctly. I adapted the demo code for Swift and came up with this basic structure, which worked for me.

    class ViewController: UIViewController, UIScrollViewDelegate {
    
        @IBOutlet var scrollView : UIScrollView!
        var layerView = UIView()
        var shapeLayer= CAShapeLayer()
    
        func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
            return layerView // Specify the layer to scroll, cannot be the UIScrollView used for scrolling
        }
        func scrollViewDidEndZooming(scrollView: UIScrollView, withView view: UIView!, atScale scale: CGFloat) {
            // This was noted as required but no inner code is necessary
        }
        override func viewDidLoad() {
            super.viewDidLoad()
            layerView.layer.addSublayer(shapeLayer) // Attach layer to the canvas view
            scrollView.addSubview(layerView) // Attach the views
            // ... Add layer content, set max and min scaling values as well as layer/view sizes to encompass content
        }
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
        }
    }
    

    I hope this helps someone else!