In macOS can a CALayer that has an NSImage as its contents be encoded / decoded?

38 Views Asked by At

Trying to decode a CALayer that was encoded with an NSImage as its .contents generates the following output in the console, and the image is not in the CALayer after decoding it.

<NSImage 0x600003390c80 Name=Rip Size={285, 298} RepProvider=<NSImageURLReferencingRepProvider:0x6000002da160 url:file:///Library/Developer/Xcode/DerivedData/CALayerTest-azbammleuklcsteocgqyjikdhnga/Build/Products/Debug/CALayerTest.app/Contents/Resources/Rip.jpg reps:(
    "NSBitmapImageRep 0x60000299eae0 Size={285, 298} ColorSpace=(not yet loaded) BPS=8 BPP=(not yet loaded) Pixels=285x298 Alpha=NO Planar=NO Format=(not yet loaded) CurrentBacking=nil (faulting) CGImageSource=0x6000002da460"
)>>
For key: contents

The code that generates that is - NSKeyedUnarchiver.unarchiveTopLevelObjectWithData:

    do {
      theData = try NSKeyedArchiver.archivedData(withRootObject: theLayer, requiringSecureCoding: false)
       }
    catch {
      print("that didnt work")
      }

    if let decodedLayer = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(theData) as? CALayer {

I'm guessing that it won't work. From Apple's Core Animation Programming guide (circa 2015-03-09) it says:

Using an Image for the Layer’s Content

Because a layer is just a container for managing a bitmap image, you can assign an image directly to the layer’s contents property. Assigning an image to the layer is easy and lets you specify the exact image you want to display onscreen. The layer uses the image object you provide directly and does not attempt to create its own copy of that image. This behavior can save memory in cases where your app uses the same image in multiple places.

I solved it by encoding the NSImage separately and making a copy of the CALayer and setting .contents to nil before encoding it. (Needed to make a copy because the CALayers are possibly attached to an existing layer). Then when loading the data - after the CALayer is decoded - re-add the NSImage.

Not 100% sure this is the right way to do this.

0

There are 0 best solutions below