lottie-ios 4.1.2 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/.github/workflows/main.yml +27 -9
  2. package/Lottie.xcodeproj/project.pbxproj +158 -70
  3. package/Lottie.xcodeproj/xcuserdata/calstephens.xcuserdatad/xcschemes/xcschememanagement.plist +2 -2
  4. package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/IDEFindNavigatorScopes.plist +5 -0
  5. package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  6. package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +258 -0
  7. package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcdebugger/Expressions.xcexplist +13 -2
  8. package/Package.swift +2 -1
  9. package/README.md +3 -3
  10. package/Rakefile +8 -4
  11. package/Sources/Private/CoreAnimation/Animations/CALayer+addAnimation.swift +16 -2
  12. package/Sources/Private/CoreAnimation/Animations/CombinedShapeAnimation.swift +1 -1
  13. package/Sources/Private/CoreAnimation/Animations/CustomPathAnimation.swift +1 -1
  14. package/Sources/Private/CoreAnimation/Animations/EllipseAnimation.swift +1 -1
  15. package/Sources/Private/CoreAnimation/Animations/GradientAnimations.swift +6 -6
  16. package/Sources/Private/CoreAnimation/Animations/LayerProperty.swift +76 -7
  17. package/Sources/Private/CoreAnimation/Animations/OpacityAnimation.swift +1 -1
  18. package/Sources/Private/CoreAnimation/Animations/RectangleAnimation.swift +1 -1
  19. package/Sources/Private/CoreAnimation/Animations/ShapeAnimation.swift +66 -102
  20. package/Sources/Private/CoreAnimation/Animations/StarAnimation.swift +2 -2
  21. package/Sources/Private/CoreAnimation/Animations/StrokeAnimation.swift +3 -3
  22. package/Sources/Private/CoreAnimation/Animations/TransformAnimations.swift +66 -17
  23. package/Sources/Private/CoreAnimation/CoreAnimationLayer.swift +55 -32
  24. package/Sources/Private/CoreAnimation/Extensions/Keyframes+combined.swift +16 -12
  25. package/Sources/Private/CoreAnimation/Layers/AnimationLayer.swift +3 -3
  26. package/Sources/Private/CoreAnimation/Layers/BaseCompositionLayer.swift +24 -11
  27. package/Sources/Private/CoreAnimation/Layers/ImageLayer.swift +2 -2
  28. package/Sources/Private/CoreAnimation/Layers/PreCompLayer.swift +1 -1
  29. package/Sources/Private/CoreAnimation/Layers/RepeaterLayer.swift +13 -2
  30. package/Sources/Private/CoreAnimation/Layers/ShapeLayer.swift +9 -1
  31. package/Sources/Private/CoreAnimation/ValueProviderStore.swift +22 -11
  32. package/Sources/Private/MainThread/LayerContainers/CompLayers/MaskContainerLayer.swift +1 -1
  33. package/Sources/Private/MainThread/LayerContainers/MainThreadAnimationLayer.swift +13 -2
  34. package/Sources/Private/MainThread/LayerContainers/Utility/LayerTransformNode.swift +16 -7
  35. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/EllipseNode.swift +1 -1
  36. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/PolygonNode.swift +2 -2
  37. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/RectNode.swift +1 -1
  38. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/StarNode.swift +2 -2
  39. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderContainers/GroupNode.swift +20 -8
  40. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/FillNode.swift +1 -1
  41. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/GradientFillNode.swift +1 -1
  42. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/GradientStrokeNode.swift +1 -1
  43. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/StrokeNode.swift +1 -1
  44. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/Text/TextAnimatorNode.swift +28 -9
  45. package/Sources/Private/Model/Assets/ImageAsset.swift +4 -3
  46. package/Sources/Private/Model/DotLottie/DotLottieAnimation.swift +2 -8
  47. package/Sources/Private/Model/DotLottie/DotLottieManifest.swift +3 -14
  48. package/Sources/Private/Model/DotLottie/DotLottieUtils.swift +11 -1
  49. package/Sources/Private/Model/DotLottie/ZipFoundation/Archive+BackingConfiguration.swift +147 -0
  50. package/Sources/Private/Model/DotLottie/ZipFoundation/Archive+Helpers.swift +351 -0
  51. package/Sources/Private/Model/DotLottie/ZipFoundation/Archive+MemoryFile.swift +183 -0
  52. package/Sources/Private/Model/DotLottie/ZipFoundation/Archive+Progress.swift +66 -0
  53. package/Sources/Private/Model/DotLottie/ZipFoundation/Archive+Reading.swift +144 -0
  54. package/Sources/Private/Model/DotLottie/ZipFoundation/Archive+ReadingDeprecated.swift +49 -0
  55. package/Sources/Private/Model/DotLottie/ZipFoundation/Archive+Writing.swift +385 -0
  56. package/Sources/Private/Model/DotLottie/ZipFoundation/Archive+WritingDeprecated.swift +91 -0
  57. package/Sources/Private/Model/DotLottie/ZipFoundation/Archive+ZIP64.swift +170 -0
  58. package/Sources/Private/Model/DotLottie/{Zip/ZipArchive.swift → ZipFoundation/Archive.swift} +150 -227
  59. package/Sources/Private/Model/DotLottie/ZipFoundation/Data+Compression.swift +403 -0
  60. package/Sources/Private/Model/DotLottie/ZipFoundation/Data+CompressionDeprecated.swift +44 -0
  61. package/Sources/Private/Model/DotLottie/{Zip → ZipFoundation}/Data+Serialization.swift +62 -0
  62. package/Sources/Private/Model/DotLottie/{Zip/ZipEntry+Serialization.swift → ZipFoundation/Entry+Serialization.swift} +7 -7
  63. package/Sources/Private/Model/DotLottie/{Zip/ZipEntry+ZIP64.swift → ZipFoundation/Entry+ZIP64.swift} +13 -19
  64. package/Sources/Private/Model/DotLottie/{Zip/ZipEntry.swift → ZipFoundation/Entry.swift} +141 -10
  65. package/Sources/Private/Model/DotLottie/ZipFoundation/FileManager+ZIP.swift +368 -0
  66. package/Sources/Private/Model/DotLottie/ZipFoundation/README.md +24 -0
  67. package/Sources/Private/Model/DotLottie/ZipFoundation/URL+ZIP.swift +32 -0
  68. package/Sources/Private/Model/Extensions/Bundle.swift +5 -14
  69. package/Sources/Private/Model/Keyframes/KeyframeGroup.swift +31 -8
  70. package/Sources/Private/Model/Objects/Transform.swift +58 -17
  71. package/Sources/Private/Model/ShapeItems/Repeater.swift +41 -7
  72. package/Sources/Private/Model/ShapeItems/ShapeTransform.swift +61 -7
  73. package/Sources/Private/Model/Text/TextAnimator.swift +37 -5
  74. package/Sources/Private/RootAnimationLayer.swift +3 -1
  75. package/Sources/Private/Utility/Extensions/AnimationKeypathExtension.swift +12 -4
  76. package/Sources/Private/Utility/Extensions/DataExtension.swift +14 -4
  77. package/Sources/Private/Utility/Primitives/BezierPathRoundExtension.swift +11 -0
  78. package/Sources/Private/Utility/Primitives/ColorExtension.swift +10 -13
  79. package/Sources/Private/Utility/Primitives/VectorsExtensions.swift +28 -6
  80. package/Sources/Public/Animation/LottieAnimationHelpers.swift +12 -10
  81. package/Sources/Public/Animation/LottieAnimationView.swift +213 -186
  82. package/Sources/Public/DotLottie/DotLottieFile.swift +11 -34
  83. package/Sources/Public/DotLottie/DotLottieFileHelpers.swift +101 -74
  84. package/Sources/Public/iOS/Compatibility/CompatibleAnimationView.swift +90 -0
  85. package/Sources/Public/iOS/LottieAnimationViewBase.swift +1 -1
  86. package/Sources/Public/macOS/LottieAnimationViewBase.macOS.swift +1 -1
  87. package/lottie-ios.podspec +1 -1
  88. package/package.json +1 -1
  89. package/LottieAnimation/LottieAnimation.xcodeproj/project.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  90. package/LottieAnimation/LottieAnimation.xcodeproj/project.xcworkspace/xcuserdata/valentinperignon.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  91. package/LottieAnimation/LottieAnimation.xcodeproj/xcuserdata/calstephens.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
  92. package/LottieAnimation/LottieAnimation.xcodeproj/xcuserdata/valentinperignon.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +0 -6
  93. package/LottieAnimation/LottieAnimation.xcodeproj/xcuserdata/valentinperignon.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
  94. package/Sources/Private/Model/DotLottie/Zip/Data+Compression.swift +0 -134
  95. package/Sources/Private/Model/DotLottie/Zip/FileManager+ZIP.swift +0 -130
  96. package/Sources/Private/Utility/Interpolatable/KeyframeGroup+Extensions.swift +0 -59
@@ -9,6 +9,77 @@ import Foundation
9
9
 
10
10
  extension DotLottieFile {
11
11
 
12
+ public enum SynchronouslyBlockingCurrentThread {
13
+ /// Loads an DotLottie from a specific filepath synchronously. Returns a `Result<DotLottieFile, Error>`
14
+ /// Please use the asynchronous methods whenever possible. This operation will block the Thread it is running in.
15
+ ///
16
+ /// - Parameter filepath: The absolute filepath of the lottie to load. EG "/User/Me/starAnimation.lottie"
17
+ /// - Parameter dotLottieCache: A cache for holding loaded lotties. Defaults to `LRUDotLottieCache.sharedCache`. Optional.
18
+ public static func loadedFrom(
19
+ filepath: String,
20
+ dotLottieCache: DotLottieCacheProvider? = DotLottieCache.sharedCache)
21
+ -> Result<DotLottieFile, Error>
22
+ {
23
+ /// Check cache for lottie
24
+ if
25
+ let dotLottieCache = dotLottieCache,
26
+ let lottie = dotLottieCache.file(forKey: filepath)
27
+ {
28
+ return .success(lottie)
29
+ }
30
+
31
+ do {
32
+ /// Decode the lottie.
33
+ let url = URL(fileURLWithPath: filepath)
34
+ let data = try Data(contentsOf: url)
35
+ let lottie = try DotLottieFile(data: data, filename: url.deletingPathExtension().lastPathComponent)
36
+ dotLottieCache?.setFile(lottie, forKey: filepath)
37
+ return .success(lottie)
38
+ } catch {
39
+ /// Decoding Error.
40
+ return .failure(error)
41
+ }
42
+ }
43
+
44
+ /// Loads a DotLottie model from a bundle by its name synchronously. Returns a `Result<DotLottieFile, Error>`
45
+ /// Please use the asynchronous methods whenever possible. This operation will block the Thread it is running in.
46
+ ///
47
+ /// - Parameter name: The name of the lottie file without the lottie extension. EG "StarAnimation"
48
+ /// - Parameter bundle: The bundle in which the lottie is located. Defaults to `Bundle.main`
49
+ /// - Parameter subdirectory: A subdirectory in the bundle in which the lottie is located. Optional.
50
+ /// - Parameter dotLottieCache: A cache for holding loaded lotties. Defaults to `LRUDotLottieCache.sharedCache`. Optional.
51
+ public static func named(
52
+ _ name: String,
53
+ bundle: Bundle = Bundle.main,
54
+ subdirectory: String? = nil,
55
+ dotLottieCache: DotLottieCacheProvider? = DotLottieCache.sharedCache)
56
+ -> Result<DotLottieFile, Error>
57
+ {
58
+ /// Create a cache key for the lottie.
59
+ let cacheKey = bundle.bundlePath + (subdirectory ?? "") + "/" + name
60
+
61
+ /// Check cache for lottie
62
+ if
63
+ let dotLottieCache = dotLottieCache,
64
+ let lottie = dotLottieCache.file(forKey: cacheKey)
65
+ {
66
+ return .success(lottie)
67
+ }
68
+
69
+ do {
70
+ /// Decode animation.
71
+ let data = try bundle.dotLottieData(name, subdirectory: subdirectory)
72
+ let lottie = try DotLottieFile(data: data, filename: name)
73
+ dotLottieCache?.setFile(lottie, forKey: cacheKey)
74
+ return .success(lottie)
75
+ } catch {
76
+ /// Decoding error.
77
+ LottieLogger.shared.warn("Error when decoding lottie \"\(name)\": \(error)")
78
+ return .failure(error)
79
+ }
80
+ }
81
+ }
82
+
12
83
  /// Loads a DotLottie model from a bundle by its name. Returns `nil` if a file is not found.
13
84
  ///
14
85
  /// - Parameter name: The name of the lottie file without the lottie extension. EG "StarAnimation"
@@ -36,49 +107,25 @@ extension DotLottieFile {
36
107
  /// - Parameter bundle: The bundle in which the lottie is located. Defaults to `Bundle.main`
37
108
  /// - Parameter subdirectory: A subdirectory in the bundle in which the lottie is located. Optional.
38
109
  /// - Parameter dotLottieCache: A cache for holding loaded lotties. Defaults to `LRUDotLottieCache.sharedCache`. Optional.
110
+ /// - Parameter dispatchQueue: A dispatch queue used to load animations. Defaults to `DispatchQueue.global()`. Optional.
39
111
  /// - Parameter handleResult: A closure to be called when the file has loaded.
40
112
  public static func named(
41
113
  _ name: String,
42
114
  bundle: Bundle = Bundle.main,
43
115
  subdirectory: String? = nil,
44
116
  dotLottieCache: DotLottieCacheProvider? = DotLottieCache.sharedCache,
117
+ dispatchQueue: DispatchQueue = .global(),
45
118
  handleResult: @escaping (Result<DotLottieFile, Error>) -> Void)
46
119
  {
47
- DispatchQueue.global().async {
48
- /// Create a cache key for the lottie.
49
- let cacheKey = bundle.bundlePath + (subdirectory ?? "") + "/" + name
120
+ dispatchQueue.async {
121
+ let result = SynchronouslyBlockingCurrentThread.named(
122
+ name,
123
+ bundle: bundle,
124
+ subdirectory: subdirectory,
125
+ dotLottieCache: dotLottieCache)
50
126
 
51
- /// Check cache for lottie
52
- if
53
- let dotLottieCache = dotLottieCache,
54
- let lottie = dotLottieCache.file(forKey: cacheKey)
55
- {
56
- DispatchQueue.main.async {
57
- /// If found, return the lottie.
58
- handleResult(.success(lottie))
59
- }
60
- return
61
- }
62
-
63
- do {
64
- /// Decode animation.
65
- guard let data = try bundle.dotLottieData(name, subdirectory: subdirectory) else {
66
- DispatchQueue.main.async {
67
- handleResult(.failure(DotLottieError.invalidData))
68
- }
69
- return
70
- }
71
- let lottie = try DotLottieFile(data: data, filename: name)
72
- dotLottieCache?.setFile(lottie, forKey: cacheKey)
73
- DispatchQueue.main.async {
74
- handleResult(.success(lottie))
75
- }
76
- } catch {
77
- /// Decoding error.
78
- LottieLogger.shared.warn("Error when decoding lottie \"\(name)\": \(error)")
79
- DispatchQueue.main.async {
80
- handleResult(.failure(error))
81
- }
127
+ DispatchQueue.main.async {
128
+ handleResult(result)
82
129
  }
83
130
  }
84
131
  }
@@ -102,38 +149,21 @@ extension DotLottieFile {
102
149
  /// Loads an DotLottie from a specific filepath.
103
150
  /// - Parameter filepath: The absolute filepath of the lottie to load. EG "/User/Me/starAnimation.lottie"
104
151
  /// - Parameter dotLottieCache: A cache for holding loaded lotties. Defaults to `LRUDotLottieCache.sharedCache`. Optional.
152
+ /// - Parameter dispatchQueue: A dispatch queue used to load animations. Defaults to `DispatchQueue.global()`. Optional.
105
153
  /// - Parameter handleResult: A closure to be called when the file has loaded.
106
154
  public static func loadedFrom(
107
155
  filepath: String,
108
156
  dotLottieCache: DotLottieCacheProvider? = DotLottieCache.sharedCache,
157
+ dispatchQueue: DispatchQueue = .global(),
109
158
  handleResult: @escaping (Result<DotLottieFile, Error>) -> Void)
110
159
  {
111
- DispatchQueue.global().async {
112
- /// Check cache for lottie
113
- if
114
- let dotLottieCache = dotLottieCache,
115
- let lottie = dotLottieCache.file(forKey: filepath)
116
- {
117
- DispatchQueue.main.async {
118
- handleResult(.success(lottie))
119
- }
120
- return
121
- }
160
+ dispatchQueue.async {
161
+ let result = SynchronouslyBlockingCurrentThread.loadedFrom(
162
+ filepath: filepath,
163
+ dotLottieCache: dotLottieCache)
122
164
 
123
- do {
124
- /// Decode the lottie.
125
- let url = URL(fileURLWithPath: filepath)
126
- let data = try Data(contentsOf: url)
127
- let lottie = try DotLottieFile(data: data, filename: url.deletingPathExtension().lastPathComponent)
128
- dotLottieCache?.setFile(lottie, forKey: filepath)
129
- DispatchQueue.main.async {
130
- handleResult(.success(lottie))
131
- }
132
- } catch {
133
- /// Decoding Error.
134
- DispatchQueue.main.async {
135
- handleResult(.failure(error))
136
- }
165
+ DispatchQueue.main.async {
166
+ handleResult(result)
137
167
  }
138
168
  }
139
169
  }
@@ -160,14 +190,16 @@ extension DotLottieFile {
160
190
  /// - Parameter name: The name of the lottie file in the asset catalog. EG "StarAnimation"
161
191
  /// - Parameter bundle: The bundle in which the lottie is located. Defaults to `Bundle.main`
162
192
  /// - Parameter dotLottieCache: A cache for holding loaded lottie files. Defaults to `LRUDotLottieCache.sharedCache` Optional.
193
+ /// - Parameter dispatchQueue: A dispatch queue used to load animations. Defaults to `DispatchQueue.global()`. Optional.
163
194
  /// - Parameter handleResult: A closure to be called when the file has loaded.
164
195
  public static func asset(
165
196
  named name: String,
166
197
  bundle: Bundle = Bundle.main,
167
198
  dotLottieCache: DotLottieCacheProvider? = DotLottieCache.sharedCache,
199
+ dispatchQueue: DispatchQueue = .global(),
168
200
  handleResult: @escaping (Result<DotLottieFile, Error>) -> Void)
169
201
  {
170
- DispatchQueue.global().async {
202
+ dispatchQueue.async {
171
203
  /// Create a cache key for the lottie.
172
204
  let cacheKey = bundle.bundlePath + "/" + name
173
205
 
@@ -183,15 +215,10 @@ extension DotLottieFile {
183
215
  return
184
216
  }
185
217
 
186
- /// Load data from Asset
187
- guard let data = Data.jsonData(from: name, in: bundle) else {
188
- DispatchQueue.main.async {
189
- handleResult(.failure(DotLottieError.invalidData))
190
- }
191
- return
192
- }
193
-
194
218
  do {
219
+ /// Load data from Asset
220
+ let data = try Data(assetName: name, in: bundle)
221
+
195
222
  /// Decode lottie.
196
223
  let lottie = try DotLottieFile(data: data, filename: name)
197
224
  dotLottieCache?.setFile(lottie, forKey: cacheKey)
@@ -240,13 +267,13 @@ extension DotLottieFile {
240
267
  handleResult(.success(lottie))
241
268
  } else {
242
269
  let task = session.dataTask(with: url) { data, _, error in
243
- guard error == nil, let data = data else {
244
- DispatchQueue.main.async {
245
- handleResult(.failure(DotLottieError.invalidData))
246
- }
247
- return
248
- }
249
270
  do {
271
+ if let error = error {
272
+ throw error
273
+ }
274
+ guard let data = data else {
275
+ throw DotLottieError.noDataLoaded
276
+ }
250
277
  let lottie = try DotLottieFile(data: data, filename: url.deletingPathExtension().lastPathComponent)
251
278
  DispatchQueue.main.async {
252
279
  dotLottieCache?.setFile(lottie, forKey: url.absoluteString)
@@ -90,6 +90,32 @@ public enum CompatibleRenderingEngineOption: Int {
90
90
  }
91
91
  }
92
92
 
93
+ /// An Objective-C compatible version of `LottieBackgroundBehavior`.
94
+ @objc
95
+ public enum CompatibleBackgroundBehavior: Int {
96
+ /// Stop the animation and reset it to the beginning of its current play time. The completion block is called.
97
+ case stop
98
+
99
+ /// Pause the animation in its current state. The completion block is called.
100
+ case pause
101
+
102
+ /// Pause the animation and restart it when the application moves to the foreground.
103
+ /// The completion block is stored and called when the animation completes.
104
+ /// - This is the default when using the Main Thread rendering engine.
105
+ case pauseAndRestore
106
+
107
+ /// Stops the animation and sets it to the end of its current play time. The completion block is called.
108
+ case forceFinish
109
+
110
+ /// The animation continues playing in the background.
111
+ /// - This is the default when using the Core Animation rendering engine.
112
+ /// Playing an animation using the Core Animation engine doesn't come with any CPU overhead,
113
+ /// so using `.continuePlaying` avoids the need to stop and then resume the animation
114
+ /// (which does come with some CPU overhead).
115
+ /// - This mode should not be used with the Main Thread rendering engine.
116
+ case continuePlaying
117
+ }
118
+
93
119
  /// An Objective-C compatible wrapper around Lottie's LottieAnimationView.
94
120
  @objc
95
121
  public final class CompatibleAnimationView: UIView {
@@ -187,6 +213,13 @@ public final class CompatibleAnimationView: UIView {
187
213
  }
188
214
  }
189
215
 
216
+ @objc
217
+ public var compatibleDictionaryTextProvider: CompatibleDictionaryTextProvider? {
218
+ didSet {
219
+ animationView.textProvider = compatibleDictionaryTextProvider?.textProvider ?? DefaultTextProvider()
220
+ }
221
+ }
222
+
190
223
  @objc
191
224
  public override var contentMode: UIView.ContentMode {
192
225
  set { animationView.contentMode = newValue }
@@ -249,6 +282,38 @@ public final class CompatibleAnimationView: UIView {
249
282
  animationView.isAnimationPlaying
250
283
  }
251
284
 
285
+ @objc
286
+ public var backgroundMode: CompatibleBackgroundBehavior {
287
+ get {
288
+ switch animationView.backgroundBehavior {
289
+ case .stop:
290
+ return .stop
291
+ case .pause:
292
+ return .pause
293
+ case .pauseAndRestore:
294
+ return .pauseAndRestore
295
+ case .forceFinish:
296
+ return .forceFinish
297
+ case .continuePlaying:
298
+ return .continuePlaying
299
+ }
300
+ }
301
+ set {
302
+ switch newValue {
303
+ case .stop:
304
+ animationView.backgroundBehavior = .stop
305
+ case .pause:
306
+ animationView.backgroundBehavior = .pause
307
+ case .pauseAndRestore:
308
+ animationView.backgroundBehavior = .pauseAndRestore
309
+ case .forceFinish:
310
+ animationView.backgroundBehavior = .forceFinish
311
+ case .continuePlaying:
312
+ animationView.backgroundBehavior = .continuePlaying
313
+ }
314
+ }
315
+ }
316
+
252
317
  @objc
253
318
  public func play() {
254
319
  play(completion: nil)
@@ -451,4 +516,29 @@ public final class CompatibleAnimationView: UIView {
451
516
  animationView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
452
517
  }
453
518
  }
519
+
520
+ /// An Objective-C compatible wrapper around Lottie's DictionaryTextProvider.
521
+ /// Use in tandem with CompatibleAnimationView to supply text to LottieAnimationView
522
+ /// when using Lottie in Objective-C.
523
+ @objc
524
+ public final class CompatibleDictionaryTextProvider: NSObject {
525
+
526
+ // MARK: Lifecycle
527
+
528
+ @objc
529
+ public init(values: [String: String]) {
530
+ self.values = values
531
+ super.init()
532
+ }
533
+
534
+ // MARK: Internal
535
+
536
+ internal var textProvider: AnimationTextProvider? {
537
+ DictionaryTextProvider(values)
538
+ }
539
+
540
+ // MARK: Private
541
+
542
+ private let values: [String: String]
543
+ }
454
544
  #endif
@@ -11,7 +11,7 @@ import UIKit
11
11
  /// The base view for `LottieAnimationView` on iOS, tvOS, watchOS, and macCatalyst.
12
12
  ///
13
13
  /// Enables the `LottieAnimationView` implementation to be shared across platforms.
14
- public class LottieAnimationViewBase: UIView {
14
+ open class LottieAnimationViewBase: UIView {
15
15
 
16
16
  // MARK: Public
17
17
 
@@ -27,7 +27,7 @@ public enum LottieContentMode: Int {
27
27
  /// The base view for `LottieAnimationView` on macOs.
28
28
  ///
29
29
  /// Enables the `LottieAnimationView` implementation to be shared across platforms.
30
- public class LottieAnimationViewBase: NSView {
30
+ open class LottieAnimationViewBase: NSView {
31
31
 
32
32
  // MARK: Public
33
33
 
@@ -8,7 +8,7 @@
8
8
 
9
9
  Pod::Spec.new do |s|
10
10
  s.name = 'lottie-ios'
11
- s.version = '4.1.2'
11
+ s.version = '4.2.0'
12
12
  s.summary = 'A library to render native animations from bodymovin json'
13
13
 
14
14
  s.description = <<-DESC
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lottie-ios",
3
- "version": "4.1.2",
3
+ "version": "4.2.0",
4
4
  "description": "Lottie is a mobile library for Android and iOS that parses Adobe After Effects animations exported as json with bodymovin and renders the vector animations natively on mobile and through React Native!",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -1,14 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
- <plist version="1.0">
4
- <dict>
5
- <key>SchemeUserState</key>
6
- <dict>
7
- <key>LottieAnimation.xcscheme_^#shared#^_</key>
8
- <dict>
9
- <key>orderHint</key>
10
- <integer>6</integer>
11
- </dict>
12
- </dict>
13
- </dict>
14
- </plist>
@@ -1,6 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <Bucket
3
- uuid = "C335EAC3-CB4B-41DF-9652-0EB8DE739C92"
4
- type = "1"
5
- version = "2.0">
6
- </Bucket>
@@ -1,14 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
- <plist version="1.0">
4
- <dict>
5
- <key>SchemeUserState</key>
6
- <dict>
7
- <key>LottieAnimation.xcscheme_^#shared#^_</key>
8
- <dict>
9
- <key>orderHint</key>
10
- <integer>0</integer>
11
- </dict>
12
- </dict>
13
- </dict>
14
- </plist>
@@ -1,134 +0,0 @@
1
- //
2
- // Data+Compression.swift
3
- // ZIPFoundation
4
- //
5
- // Copyright © 2017-2021 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
6
- // Released under the MIT License.
7
- //
8
- // See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
9
- //
10
-
11
- import Foundation
12
-
13
- #if canImport(zlib)
14
- import zlib
15
- #endif
16
-
17
- /// A custom handler that consumes a `Data` object containing partial entry data.
18
- /// - Parameters:
19
- /// - data: A chunk of `Data` to consume.
20
- /// - Throws: Can throw to indicate errors during data consumption.
21
- typealias ZipDataCallback = (_ data: Data) throws -> Void
22
- /// A custom handler that receives a position and a size that can be used to provide data from an arbitrary source.
23
- /// - Parameters:
24
- /// - position: The current read position.
25
- /// - size: The size of the chunk to provide.
26
- /// - Returns: A chunk of `Data`.
27
- /// - Throws: Can throw to indicate errors in the data source.
28
- typealias ZipDataProvider = (_ position: Int64, _ size: Int) throws -> Data
29
-
30
- extension Data {
31
- enum CompressionError: Error {
32
- case invalidStream
33
- case corruptedData
34
- }
35
-
36
- /// Decompress the output of `provider` and pass it to `consumer`.
37
- /// - Parameters:
38
- /// - size: The compressed size of the data to be decompressed.
39
- /// - bufferSize: The maximum size of the decompression buffer.
40
- /// - provider: A closure that accepts a position and a chunk size. Returns a `Data` chunk.
41
- /// - consumer: A closure that processes the result of the decompress operation.
42
- /// - Returns: The checksum of the processed content.
43
- static func decompress(size: Int64, bufferSize: Int, provider: ZipDataProvider, consumer: ZipDataCallback) throws -> UInt32 {
44
- try process(
45
- operation: COMPRESSION_STREAM_DECODE,
46
- size: size,
47
- bufferSize: bufferSize,
48
- provider: provider,
49
- consumer: consumer)
50
- }
51
-
52
- /// Calculate the `CRC32` checksum of the receiver.
53
- ///
54
- /// - Parameter checksum: The starting seed.
55
- /// - Returns: The checksum calculated from the bytes of the receiver and the starting seed.
56
- func crc32(checksum: UInt32) -> UInt32 {
57
- #if canImport(zlib)
58
- return withUnsafeBytes { bufferPointer in
59
- let length = UInt32(count)
60
- return UInt32(zlib.crc32(UInt(checksum), bufferPointer.bindMemory(to: UInt8.self).baseAddress, length))
61
- }
62
- #else
63
- return builtInCRC32(checksum: checksum)
64
- #endif
65
- }
66
-
67
- }
68
-
69
- import Compression
70
-
71
- extension Data {
72
- static func process(
73
- operation: compression_stream_operation,
74
- size: Int64,
75
- bufferSize: Int,
76
- provider: ZipDataProvider,
77
- consumer: ZipDataCallback)
78
- throws -> UInt32
79
- {
80
- var crc32 = UInt32(0)
81
- let destPointer = UnsafeMutablePointer<UInt8>.allocate(capacity: bufferSize)
82
- defer { destPointer.deallocate() }
83
- let streamPointer = UnsafeMutablePointer<compression_stream>.allocate(capacity: 1)
84
- defer { streamPointer.deallocate() }
85
- var stream = streamPointer.pointee
86
- var status = compression_stream_init(&stream, operation, COMPRESSION_ZLIB)
87
- guard status != COMPRESSION_STATUS_ERROR else { throw CompressionError.invalidStream }
88
- defer { compression_stream_destroy(&stream) }
89
- stream.src_size = 0
90
- stream.dst_ptr = destPointer
91
- stream.dst_size = bufferSize
92
- var position: Int64 = 0
93
- var sourceData: Data?
94
- repeat {
95
- let isExhausted = stream.src_size == 0
96
- if isExhausted {
97
- do {
98
- sourceData = try provider(position, Int(Swift.min(size - position, Int64(bufferSize))))
99
- position += Int64(stream.prepare(for: sourceData))
100
- } catch { throw error }
101
- }
102
- if let sourceData = sourceData {
103
- sourceData.withUnsafeBytes { rawBufferPointer in
104
- if let baseAddress = rawBufferPointer.baseAddress {
105
- let pointer = baseAddress.assumingMemoryBound(to: UInt8.self)
106
- stream.src_ptr = pointer.advanced(by: sourceData.count - stream.src_size)
107
- let flags = sourceData.count < bufferSize ? Int32(COMPRESSION_STREAM_FINALIZE.rawValue) : 0
108
- status = compression_stream_process(&stream, flags)
109
- }
110
- }
111
- if operation == COMPRESSION_STREAM_ENCODE, isExhausted { crc32 = sourceData.crc32(checksum: crc32) }
112
- }
113
- switch status {
114
- case COMPRESSION_STATUS_OK, COMPRESSION_STATUS_END:
115
- let outputData = Data(bytesNoCopy: destPointer, count: bufferSize - stream.dst_size, deallocator: .none)
116
- try consumer(outputData)
117
- if operation == COMPRESSION_STREAM_DECODE { crc32 = outputData.crc32(checksum: crc32) }
118
- stream.dst_ptr = destPointer
119
- stream.dst_size = bufferSize
120
- default: throw CompressionError.corruptedData
121
- }
122
- } while status == COMPRESSION_STATUS_OK
123
- return crc32
124
- }
125
- }
126
-
127
- extension compression_stream {
128
- fileprivate mutating func prepare(for sourceData: Data?) -> Int {
129
- guard let sourceData = sourceData else { return 0 }
130
-
131
- src_size = sourceData.count
132
- return sourceData.count
133
- }
134
- }