Endanke
Endanke

Reputation: 887

Custom drawing UIView crashes on iOS 9 but works on other systems

I have a custom UIView that includes a custom CALayer to draw some shapes and play an animation. For the last couple releases of the app it was working without any issue. The last published version is consistently crashing on iOS 9, but works on other versions of iOS.

The error log on Crashlytics shows EXC_BAD_ACCESS KERN_INVALID_ADDRESS and the stack trace indicates the constructor of the custom view as the root of the crash.

Here's a simplified example, which crashes on my iOS 9 iPad Mini 2 device but works on my newer models.

import UIKit

class CustomView: UIView {
    private let customLayer: CustomLayer = CustomLayer()

    init(color: UIColor) {
        super.init(frame: .zero)
        self.customLayer.color = color
    }

    required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") }

    override func didMoveToWindow() {
       super.didMoveToWindow()
       setupAnimation()
    }

    private func setupAnimation() {
       ...
   }
}

fileprivate class CustomLayer: CALayer {
    var color: UIColor = .white

    override init() { super.init() }
    override init(layer: Any) { super.init(layer: layer)  }
    required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") }
    override func draw(in ctx: CGContext) { 
    // Some CoreGraphics drawing commands
    }


}

Upvotes: 0

Views: 271

Answers (2)

Juan Romero
Juan Romero

Reputation: 41

We are having this as well after converting some classes to swift. Only iOS 9. Our workaround is to use computed properties, and get/set the values from there. In our case using objc associated object values, but could be as well a dictionary/cache or whatever external construct that doesn't have to be stored in the CALayer subclass instance (custom property), but accessible via the computed properties getters/setters.

Upvotes: 1

Endanke
Endanke

Reputation: 887

Shortly after writing this example I've found an explanation on the Apple Developer Forums: https://forums.developer.apple.com/thread/131551

It seems like this issue is caused by latest Xcode update. Currently I'm using Xcode 11.4.1 and the crash happens consistently on iOS 9. The code was working in the previous version of the IDE without any problems.

Based on the forum discussion, the bug is specifically related to the custom properties of a CALayer subclass. As a workaround, I moved the property initialisation in the constructor of the custom layer and now it works:

class CustomView: UIView {
    private let customLayer: CustomLayer

    init(color: UIColor) {
        self.customLayer.color = CustomLayer(color: color)
        super.init(frame: .zero)
    }
    ...
}
fileprivate class RayLayer: CALayer {
    private let color: UIColor

    init(color: UIColor) {
        self.color = color
        super.init()
    }
    override init(layer: Any) {
        self.color = .white
        super.init(layer: layer)
    }
    ...
}

Upvotes: 0

Related Questions