Lottie-ios: lottie crashed in AnimationContainer.init() on iOS9 device when used Xcode11.4

Created on 25 Mar 2020  ·  32Comments  ·  Source: airbnb/lottie-ios


When I compiled and ran with the latest version of Xcode 11.4, there was a crash anywhere I used Lottie on iOS 9 devices

Check these before submitting:

  • [✔️] The issue doesn't involve an Unsupported Feature
  • [✔️] This issue isn't related to another open issue

This issue is a:

  • [] Non-Crashing Bug (Visual or otherwise)
  • [✔️] Crashing Bug
  • [] Feature Request
  • [] Regression (Something that once worked, but doesn't work anymore)

Which Version of Lottie are you using?

Lottie 3.1.6

What Platform are you on?

  • [] MacOS
  • [✔️] iOS

What Language are you in?

  • [✔️] Swift
  • [] Objective-C

Expected Behavior

Actual Behavior

Code Example

Animation JSON

Most helpful comment

I have tried downgrading to Lottie 2.5.3, which is written in Objective-C. This works without crashes with Xcode 11.5. As @brunsman pointed out, the issue seems to be related to properties on subclasses of CALayer written in Swift. While I guess it’s not ideal to downgrade, I found rewriting code to work with Lottie 2.5.3 to be quite simple, and definitely worth it to keep up with newer Xcode versions.

All 32 comments

Same for me, only iOS 9 devices will crash, the same code on Xcode 11.3 is OK.

Crashed: com.apple.main-thread
0 libobjc.A.dylib 0x1976e8160 objc_release + 16
1 Lottie 0x101d7cdac specialized AnimationContainer.init(animation:imageProvider:textProvider:) + 608 (:608)
2 Lottie 0x101d84358 AnimationView.makeAnimationLayer() + 268 (AnimationContainer.swift:268)
3 Lottie 0x101d83de4 AnimationView.animation.setter + 76 (:76)

The example project in the repo can reproduce the crash, with Xcode 11.4 on an iOS 9 device. Change the deployment target to 9.0 first.

Same for me, only iOS 9 devices will crash, the same code on Xcode 11.3 is OK.

Crashed: com.apple.main-thread
0 libobjc.A.dylib 0x1976e8160 objc_release + 16
1 Lottie 0x101d7cdac specialized AnimationContainer.init(animation:imageProvider:textProvider:) + 608 (:608)
2 Lottie 0x101d84358 AnimationView.makeAnimationLayer() + 268 (AnimationContainer.swift:268)
3 Lottie 0x101d83de4 AnimationView.animation.setter + 76 (:76)

Same for me

Can confirm this problem on iOS 9 with Xcode 11.4 as well. Enabling Zombie Objects in Xcode 11.4 results in the following output before crashing the application: *** -[Lottie.AnimationContainer release]: message sent to deallocated instance 0x<address>

Same problem here. I blame the changed embedding of frameworks in Xcode 11.4. Downgraded to Xcode 11.3 for now and waiting for Apple to fix the embedding of frameworks.

@brunsman Do you have more details on what the change in embedding of frameworks entails?

After digging into the issue more, I can now isolate the issue to something else. Will post the same here for reference, see https://forums.developer.apple.com/thread/131551

The code seems related to Xcode 11.4, ios 9 devices, and custom CALayers with properties.

To see this problem, Create an extension of an CALayer:

class CustomLayer: CALayer {  
   var someProperty: CGFloat = 0  
}

Now programmatically create such a layer, e.g. in a viewDidLoad

let customLayer = CustomLayer()

Compile and run this on a iOS 9 device (my tests were with an iPhone 4S with iOS 9.3.6). The device crashes when initializing the layer. It is deallocated BEFORE it can actually set the property on the customLayer. Enable zombies for a more detailed stack trace.

Since lottie uses custom CALayers with properties, it now crashes on iOS 9 devices when using Xcode 11.4. Hoping for a fix or workaround from Apple. Filed a bug report about it.

Great work @brunsman ! Looking forward to hearing the about the response.

@brunsman I tried to circumvent the initializer of CALayer in Swift by making a simple category for CALayer in Objective-C:

CALayer+Init.h

#import <QuartzCore/QuartzCore.h>

NS_ASSUME_NONNULL_BEGIN

@interface CALayer (Init)
+(instancetype)newInstance;
@end

NS_ASSUME_NONNULL_END

CALayer+Init.m

#import "CALayer+Init.h"

@implementation CALayer (Init)
+(instancetype)newInstance {
    return [[CALayer alloc] init];
}
@end

Making use of the class method in this category seems to work.

class CustomLayer: CALayer {
    var someProperty: CGFloat = 0
}

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        let customLayer = CustomLayer.newInstance() // this seems to work
        let customLayer2 = CustomLayer() // <- this still crashes
        view.layer.addSublayer(customLayer)
        view.layer.addSublayer(customLayer)
    }
}

Edit:

Unfortunately, trying to access the property on CustomLayer after making use of the class method in the category mentioned above, I get a runtime error: "Thread 1: EXC_BAD_ACCESS (code=2, address=0x.......)"

Interestingly, changing the property to be a let instead of var, does not lead to a crash. I.e.:

class CustomLayer: CALayer {
    let someProperty: CGFloat = 0
}

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        let customLayer = CustomLayer()
        view.layer.addSublayer(customLayer)
    }
}

@hakonk If you find a workaround, that would be great! So far, no dice.

Edit: XCode 11.4.1 also does not fix this issue. Still waiting for a response from Apple.

@brunsman The approach above with the Objective-C category is flawed for sure. My colleagues have pointed me in the direction of reading up on CALayer and the magic that happens under the hood, so I'll do that when I have time.

I attempted to make use of Objective-C's runtime capabilities (associated objects) to implement a property on a subclass of CALayer:

class CustomLayer: CALayer {
    private static var somePropertyHandle = 0
    var someProperty: CGFloat {
        get {
            guard let val = objc_getAssociatedObject(
                self,
                &CustomLayer.somePropertyHandle
            ) as? CGFloat else { fatalError("No obj found") }
            return val
        }
        set {
            objc_setAssociatedObject(
                self,
                &CustomLayer.somePropertyHandle,
                newValue,
                objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC
            )
        }
    }
}

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        let customLayer = CustomLayer()
        // needs to be assigned, or else the computed property logic will crash
        customLayer.someProperty = 123
        print(customLayer.someProperty)
        view.layer.addSublayer(customLayer)
    }
}

While it works, it's a cumbersome and somewhat hacky approach for just implementing a simple property.

Reported the bug to apple on the 15th of april. Got an update from Apple:

Custom CALayer with properties crashes on iOS 9 devices
15 april 2020, 8:36 AM — FB7664233
Recent Similar Reports: Less than 10
Resolution: Potential fix identified - For a future OS update

Hoping for this best and that the new xCode will fix the problem...

XCode 11.5 GM is out and the release notes state:

Fixed an issue with incorrect code generation when targeting armv7 devices. (61901594)

Is it the bug we are hunting?
Anyone have chance to test it?

Many thanks

@falcon283 @brunsman
I tried compiling and running with Xcode Version 11.5 (11E608c) and I'm still getting -[Lottie.AnimationContainer release]: message sent to deallocated instance (Zombie objects enabled).

@falcon283 @brunsman

I tried compiling and running with Xcode Version 11.5 (11E608c) and I'm still getting -[Lottie.AnimationContainer release]: message sent to deallocated instance (Zombie objects enabled).

Thanks a lot for the feedback @hakonk

It looks like the issue is still present in the latest Xcode 11.6 beta (11N700h).

It looks like the issue is still present in the latest Xcode 11.6 beta (11N700h).

This is so bad :(
Thanks for keeping us posted.

Hii, For the moment the only solution to fix the issue is to rollback to Xcode 11.3 ? Thank you

I have tried downgrading to Lottie 2.5.3, which is written in Objective-C. This works without crashes with Xcode 11.5. As @brunsman pointed out, the issue seems to be related to properties on subclasses of CALayer written in Swift. While I guess it’s not ideal to downgrade, I found rewriting code to work with Lottie 2.5.3 to be quite simple, and definitely worth it to keep up with newer Xcode versions.

Hii, For the moment the only solution to fix the issue is to rollback to Xcode 11.3 ? Thank you

Yes,It's work.

Did anyone try testing with Xcode 12 beta?

@caioremedio When testing on iOS 9 with a 32 bit device, I'm still getting the crashes, even with Xcode 12. I've sent them a report with Feedback assistant, but I haven't gotten a reply. @brunsman Did you get a reply from Apple?

@caioremedio When testing on iOS 9 with a 32 bit device, I'm still getting the crashes, even with Xcode 12. I've sent them a report with Feedback assistant, but I haven't gotten a reply. @brunsman Did you get a reply from Apple?

No.... and Apple even reverted the resolution from "Potential fix identified - For a future OS update" to "Open". I doubt they will ever fix this... I stopped using Lottie on iOS < 11.

Wow, that's a bummer, @brunsman! Anyway, it's interesting to know that the issue is still open.

xcode 12.0.1 still crash !!!!!!!!!!

How to fix this?

xcode 12.1 still crash

Maybe it is time to consider dropping support for iOS9 in your app.

same to me. xcode 12.0

Xcode 12.3 still crash. 😥

截屏2021-02-26 上午11 27 37
Version 12.4 (12D4e)

I switched to a gif animation in Kingfisher's AnimatedImageView only on iOS9 instead of lottie's way .

Was this page helpful?
0 / 5 - 0 ratings