9

I get this error:

fatal error: use of unimplemented initializer 'init(layer:)' for class 'MyProject.AccordionLayer'

using the following code. In my view controller:

override func viewDidLoad() {
    let view = self.view as! AccordionView!
    view.launchInitializationAnimations()
}

In my view:

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

    for var i = 0; i < self.accordions.count; ++i {
        var layer = AccordionLayer(accordion: self.accordions[i])
        layer.accordion = self.accordions[i]
        layer.frame = CGRectMake(0, CGFloat(i) * self.getDefaultHeight(), self.frame.width, self.getDefaultHeight())
        self.layer.addSublayer(layer)
        layer.setNeedsDisplay()
        layers.append(layer)
    }
}

func launchInitializationAnimations() {
    for layer in self.layer.sublayers {
        var animation = CABasicAnimation(keyPath: "topX")
        animation.duration = 2.0
        animation.fromValue = CGFloat(0.0)
        animation.toValue = CGFloat(200.0)
        layer.addAnimation(animation, forKey: "animateTopX")
    }
}

And in my subclassed CALayer

var topX : Int
init(accordion: (color: CGColorRef!, header: String, subtitle: String, image: UIImage?)!) {

    // Some initializations
    // ...

    super.init()
}

I also implement needsDisplayForKey, drawInContext.

I have seen 2-3 other questions with the same error message but I can't really figure out how it is related to my specific case on my own.

Why is CABasicAnimation trying to instantiate a new (my custom) CALayer?

Tobias
  • 139
  • 5
  • Which line throws the error? – Duncan C Aug 08 '15 at 13:27
  • Xcode marks the line `class AccordionLayer : CALayer {` with the message "Thread 1: EXC_BAD_INSTRUCTION". It happens immediately when `layer.addAnimation(animation, forKey: "animateTopX")` is called. It seems like `CA::Layer::layer_at_time(CA::Transaction*, double, bool, bool)` throws the error. – Tobias Aug 08 '15 at 13:34
  • You didn't post that code. If you want help with a crash at a particular line, it would help if you posted the actual code that was crashing. – Duncan C Aug 09 '15 at 18:29

2 Answers2

10

I just ran into the same issue, and I got it working after adding the init(layer:) to my custom CALayer:

override init(layer: Any) {
    super.init(layer: layer)
}

I hope it helps whoever get here.


EDIT As Ben Morrow comments, in your override you also have to copy across the property values from your custom class. For an example, see his https://stackoverflow.com/a/38468678/341994.

matt
  • 515,959
  • 87
  • 875
  • 1,141
gfpacheco
  • 2,831
  • 2
  • 33
  • 50
  • 3
    Within the body, you also have to initialize each property from your custom class manually. I figured that out on this question: http://stackoverflow.com/questions/38468515/cabasicanimation-creates-empty-default-value-copy-of-calayer/38468678#38468678 – Ben Morrow Jul 19 '16 at 21:19
  • @nik-kov In an edit, do not introduce extra code contrary to intentions of question / answer. If you have your own situation where this worked, submit it as an _answer_. – matt Apr 23 '19 at 16:39
  • @matt the extra code needed here, because it rely on comment of Ben Morrow and is mandatory to proper use of this method! – Nike Kov Apr 23 '19 at 16:43
  • @NikKov But that code is in https://stackoverflow.com/a/38468678/341994. It is appropriate _there_, not _here_. It applies to _that_ question, not _this_ one. And there is already a comment linking to it, so your edit adds nothing except to deface the existing answer. – matt Apr 23 '19 at 17:22
  • Not anybody read comments, even you, i think, noticed the comment only when i writed about it (and voted it up). My opinion that if we can make things better and somebody's life better, we should do it. Now the people who not read the comments could miss it and waste time with strange behaviour. And that because formal rules. – Nike Kov Apr 23 '19 at 18:43
  • 1
    @NikKov Okay, I'll add the link to Ben Morrow's answer into the question so there can be no missing it. (This is indeed a formally difficult situation. It would have been improper for Ben Morrow merely to repeat his answer here as a separate answer; his link in a comment was the right thing to do. Yet comments can be missed and can die. And we definitely want to help future users.) – matt Apr 23 '19 at 18:54
  • It seems like the rule of thumb is to not make custom layers that contain other layers (since you can't easily copy them). – Chris Conover May 22 '20 at 17:07
7

Why is CABasicAnimation trying to instantiate a new (my custom) CALayer?

Because animation involves making a copy of your layer to act as the presentation layer.

matt
  • 515,959
  • 87
  • 875
  • 1,141