Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(ios): use RiveFile.init(data:) initializer over init(byteArray:)
The (likely) most common use of all `RiveFile` initializers is the `RiveFile.init(name:extension:in:loadCdn:customLoader)` initializer available in `RiveFile+Extensions.swift`. This is the initializer called when a (view) model is initialized with a file name. However, some crash reports are showing that this function is crashing within the Swift runtime. I believe that under certain conditions (I've been unable to reproduce, unfortunately), the Swift runtime is crashing when initializing new types, or bridging between Swift and ObjC - I think that minimizing the usage of different types and bridging may fix some of these crashes. By switching from `init(byteArray:`) to `init(data:)`, we can remove some (extra) initialization, casting, and bridging between Swift and ObjC. In the current codepath, there is first new initialization within Swift from `Data` to `[UInt8]` (allowed because `Data` conforms to `Sequence`), which then gets bridged to Objective-C as `NSArray<NSNumber*>*`. Notice the additional bridge from `UInt8` to `NSNumber`, since ObjC can't directly handle Swift value types. So, bytes are getting transformed into a new type - from Swift `Data`, to `UInt8`, to an `NSObject` (since `NSNumber` is a reference type, required for use with `NSArray`). From here, _another_ byte array is created, converting each `NSNumber` back into a byte representation. `init(data:)` is a simpler solution - since `Data` bridges between Swift and ObjC (as NSData), we can then treat the new `NSData.bytes` as a `UInt8*` to pass to the C++ runtime, without having to allocate a new byte array, or bridging between Swift primitives and ObjC types. ## Current Codepath - Grab the file data as `Data` - Initialize a new array - the data as `[UInt8]` - Pass the bytes to `init(byteArray:`) - This bridges `[UInt8]` to `NSArray<NSNumber*>*` - Create a _new_ byte array from the supplied array. - Into the C++ runtime… - The file loads ## New Codepath - Grab the file data as `Data` - Pass the data to `init(data:)` - This bridges `Data` to `NSData` - Cast `data.bytes` to UInt8* - Into the C++ runtime… - The file loads ## Origin It seems like some of these changes occurred when out-of-band asset support was added to the iOS runtime. There were some new `RiveFile` initializers added; I'm not sure if there was an intention of switching which was used or not. ## Testing Nearly the entirety of the Example app uses file name initialization. I ran through the entire app and ensured each animation loaded as intended (both in the Simulator and on a physical device). Diffs= 11cf3a1ad9 feat(ios): use RiveFile.init(data:) initializer over init(byteArray:) (#9020) Co-authored-by: David Skuza <[email protected]>
- Loading branch information