Repository: airbnb/lottie-ios
File: Sources/Private/CoreAnimation/Layers/TextLayer.swift (Swift)

Code before:

import QuartzCore

/// The `CALayer` type responsible for rendering `TextLayer`s
final class TextLayer: BaseCompositionLayer {

  // MARK: Lifecycle

  init(
    textLayerModel: TextLayerModel,
    context: LayerContext)
    throws
  {
    self.textLayerModel = textLayerModel
    super.init(layerModel: textLayerModel)
    setupSublayers()
    try configureRenderLayer(with: context)
  }

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

  override func setupAnimations(context: LayerAnimationContext) throws {
    try super.setupAnimations(context: context)
    let customText = context.textProvider.textFor(keypathName: context.currentKeypath.fullPath, sourceText: "text layer text")
    renderLayer.text = customText
  }


  /// Called by CoreAnimation to create a shadow copy of this layer
  /// More details: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init
  override init(layer: Any) {
    guard let typedLayer = layer as? Self else {
      fatalError("\(Self.self).init(layer:) incorrectly called with \(type(of: layer))")
    }

    textLayerModel = typedLayer.textLayerModel
    super.init(layer: typedLayer)
  }

  // MARK: Internal

  func configureRenderLayer(with context: LayerContext) throws {
    // We can't use `CATextLayer`, because it doesn't support enough features we use.
    // Instead, we use the same `CoreTextRenderLayer` (with a custom `draw` implementation)
    // used by the Main Thread rendering engine. This means the Core Animation engine can't
    // _animate_ text properties, but it can display static text without any issues.
    let text = try textLayerModel.text.exactlyOneKeyframe(context: context, description: "text layer text")

    // The Core Animation engine doesn't currently support `TextAnimator`s.

Review comment (suggestion):
Would it be possible to pass in the actual source text like here: 
https://github.com/airbnb/lottie-ios/blob/167812e8ce59698144714b81a4132d3d188f2a39/Sources/Private/MainThread/LayerContainers/CompLayers/TextCompositionLayer.swift#L115

```suggestion
    let sourceText = try textLayerModel.text.exactlyOneKeyframe(context: context, description: "text layer text")
    let customText = context.textProvider.textFor(keypathName: context.currentKeypath.fullPath, sourceText: sourceText )
```

I think the `textLayerModel.text.exactlyOneKeyframe` code (currently on line 51) can be removed from `configureRenderLayer`.

Code after:

import QuartzCore

/// The `CALayer` type responsible for rendering `TextLayer`s
final class TextLayer: BaseCompositionLayer {

  // MARK: Lifecycle

  init(
    textLayerModel: TextLayerModel,
    context: LayerContext)
    throws
  {
    self.textLayerModel = textLayerModel
    super.init(layerModel: textLayerModel)
    setupSublayers()
    try configureRenderLayer(with: context)
  }

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

  /// Called by CoreAnimation to create a shadow copy of this layer
  /// More details: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init
  override init(layer: Any) {
    guard let typedLayer = layer as? Self else {
      fatalError("\(Self.self).init(layer:) incorrectly called with \(type(of: layer))")
    }

    textLayerModel = typedLayer.textLayerModel
    super.init(layer: typedLayer)
  }

  // MARK: Internal

  override func setupAnimations(context: LayerAnimationContext) throws {
    try super.setupAnimations(context: context)
    let textAnimationContext = context.addingKeypathComponent(textLayerModel.name)

    let sourceText = try textLayerModel.text.exactlyOneKeyframe(
      context: textAnimationContext,
      description: "text layer text")

    renderLayer.text = context.textProvider.textFor(
      keypathName: textAnimationContext.currentKeypath.fullPath,
      sourceText: sourceText.text)

    renderLayer.sizeToFit()
  }