Search code examples
iosswiftdelegatesswift3calayer

How can I set a delegate for a CALayer?


I'm trying to set a CALayer's delegate so that I can use draw(_:in:). The documentation describes how to do it. But as soon as I set the delegate, there's a runtime error:

Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)

Here's code that generates an error. Replace ViewController.swift in the Single View Application template in Xcode 8.2.1:

import UIKit
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let myLayer = CALayer()
        myLayer.delegate = LayerDelegate()
        view.layer.addSublayer(myLayer)
    }
}

class LayerDelegate: NSObject, CALayerDelegate {
}

Solution

  • The object is removed from memory because there is no strong reference to it. As the other @Robert pointed out, CALayer's delegate is weak and once you leave the scope, which is the viewDidLoad() function, the object is removed from memory.

    You need to make sure that it is not deallocated. You can add a property to your class. This will live as long as the class lives.

    class ViewController: UIViewController {
        let layerDelegate = LayerDelegate()
        override func viewDidLoad() {
            super.viewDidLoad()
            let myLayer = CALayer()
            myLayer.delegate = layerDelegate
            view.layer.addSublayer(myLayer)
        }
    }