Search code examples
iosuiviewuikitcalayer

UIView: cannot add multiple CALayer, only the root one appears


I am trying to add some sublayers to the root view layer. The idea is to mix a yellow and a red shadow for the view.

I tried this:

class ViewController: UIViewController {
    @IBOutlet weak var testView: UIView! {
        didSet {
            testView.backgroundColor = .white
            testView.layer.cornerRadius = 10.0
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .black
        
        testView.layer.shadowColor = UIColor.yellow.cgColor
        testView.layer.shadowOpacity = 1.0
        testView.layer.shadowRadius = 24.0
        
        let layer1 = CALayer()
        layer1.frame = testView.bounds
        layer1.shadowColor = UIColor.red.cgColor
        layer1.shadowOpacity = 1.0
        layer1.shadowRadius = 24.0
        testView.layer.addSublayer(layer1)
    }
}

But only the root layer appears (the yellow one), not the red sublayer:

enter image description here

Why is this happening? Thank you for your help


Solution

  • Two issues...

    1. For a layer to have a shadow, it must have a background color.
    2. testView may not be its final size in viewDidLoad() ... You should add the layer either after viewDidLoad, or subclass UIView and set the layer's frame in layoutSubviews

    Give this a quick try:

    class SubLayerShadowViewController: UIViewController {
    
        let testView = UIView()
        
        override func viewDidLoad() {
            super.viewDidLoad()
            view.backgroundColor = .black
            
            testView.translatesAutoresizingMaskIntoConstraints = false
            view.addSubview(testView)
    
            let g = view.safeAreaLayoutGuide
            
            NSLayoutConstraint.activate([
                testView.widthAnchor.constraint(equalToConstant: 240.0),
                testView.heightAnchor.constraint(equalTo: testView.widthAnchor),
                testView.centerXAnchor.constraint(equalTo: g.centerXAnchor),
                testView.centerYAnchor.constraint(equalTo: g.centerYAnchor),
            ])
            
            testView.backgroundColor = .white
            testView.layer.cornerRadius = 10.0
            
            testView.layer.shadowColor = UIColor.yellow.cgColor
            testView.layer.shadowOpacity = 1.0
            testView.layer.shadowRadius = 24.0
    
            // move this out of viewDidLoad()
            //let layer1 = CALayer()
            //layer1.cornerRadius = 10.0
            //layer1.frame = testView.bounds
            //layer1.shadowColor = UIColor.red.cgColor
            //layer1.shadowOpacity = 1.0
            //layer1.shadowRadius = 24.0
            //testView.layer.addSublayer(layer1)
    
        }
    
        override func viewDidLayoutSubviews() {
            super.viewDidLayoutSubviews()
            
            let layer1 = CALayer()
            layer1.cornerRadius = 10.0
            layer1.frame = testView.bounds
            layer1.shadowColor = UIColor.red.cgColor
            layer1.shadowOpacity = 1.0
            layer1.shadowRadius = 24.0
            
            // set this layer's backgroundColor to the view's backgroundColor
            layer1.backgroundColor = testView.backgroundColor?.cgColor
    
            testView.layer.addSublayer(layer1)
    
        }
    
    }