1

I'm trying to create copies of CAShapeLayer in swift but I'm getting a crash

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[CAShapeLayer copyWithZone:]: unrecognized selector sent to instance 0x282e87e60'

which extra steps should I take to allow CALayer .copy() work without crashing the app? Even if I don't cast the result of .copy() it stills fails exactly at that copy() line...

private var drawLines: [CAShapeLayer]
func getCopiedLayers() -> [CAShapeLayer] {
    return drawLines.compactMap { layer -> CAShapeLayer? in
        return layer.copy() as? CAShapeLayer
    }
}

what I'm doing wrong here? Thanks in advance for the answers

Lucas
  • 746
  • 8
  • 23

1 Answers1

2

CALayer does not conform to NSCopying from API, but it conforms to NSSecureCoding, so it is possible to add copying capability as below

Tested with Xcode 11.2 / iOS 13.2 (with CAShapeLayer & CAGradientLayer)

extension CALayer : NSCopying {
    public func copy(with zone: NSZone? = nil) -> Any {
        if let data = try? NSKeyedArchiver.archivedData(withRootObject: self, requiringSecureCoding: false) {
            if let newInstance = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) {
                return newInstance
            }
        }
        fatalError() // << should never got here
    }
}

Now, it is possible to call layer.copy() to any layer (theoretically) without exception.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Asperi
  • 228,894
  • 20
  • 464
  • 690