A Swift library to take the power of UIView.animateWithDuration(_:, animations:...) to a whole new level - layers, springs, chain-able animations and mixing view and layer animations together!

Overview

ver 2.0

NB! Breaking changes in 2.0 - due to a lot of requests EasyAnimation does NOT automatically install itself when imported. You need to enable it by calling EasyAnimation.enable() somewhere in your code (AppDelegate is a good idea).

The library doesn't use any private APIs - apps using it should be fine for release on the App Store.

Intro
Layer Animations
Spring Layer Animations
Chain Animations
Cancel Chain Animations
Installation
Credit
License
Version History

Intro

UIView.animateWithDuration:animations: is really easy to use and you're so familiar with its syntax that you often want it to do just a bit more for you automatically. But it doesn't and you need to import Bloated.framework by Beginner Ninja Coder in order to make a bit more advanced animations than what animateWithDuration:animations: allows you to.

EasyAnimation extends what UIKit offers in terms of animations and makes your life much easier because you can do much more without learning some perky new syntax.

In version 2.0 and higher to enable all EasyAnimation features you need to run once this code - AppDelegate is a good place since it'll enable EasyAnimation as soon as your app starts.

    EasyAnimation.enable()

In your other classes you don't need to import EasyAnimation or do anything else. Once you call enable() afterwards you use the normal UIKit APIs like usual.

Easy Layer Animations

EasyAnimation allows you to animate your layers straight from animate(duration:animations:...). No more CABasicAnimation code for you. Just adjust the properties of your layers from within the animations block and EasyAnimation will take care of the rest:

CoreAnimation (before)
    let anim = CABasicAnimation(keyPath: "position.x")
    anim.fromValue = 100.0
    anim.toValue = 200.0
    anim.duration = 2.0
    view.layer.addAnimation(anim, forKey: nil)
EasyAnimation (after)
    UIView.animate(duration: 2.0, animations: {
        self.view.layer.position.x = 200.0
    })

(OK, this example actually works fine also without EasyAnimation but I still keep it here for illustrative purpose)

Or if you need to specify delay, animation options and/or animation curve:

CoreAnimation (before)
    let anim = CABasicAnimation(keyPath: "position.x")
    anim.fromValue = 100.0
    anim.toValue = 200.0
    anim.duration = 2.0
    anim.fillMode = kCAFillModeBackwards
    anim.beginTime = CACurrentMediaTime() + 2.0
    anim.timingFunction = CAMediaTimingFunction(name: 
        kCAMediaTimingFunctionEaseOut)
    anim.repeatCount = Float.infinity
    anim.autoreverses = true
    view.layer.addAnimation(anim, forKey: nil)
EasyAnimation (after)
    UIView.animate(duration: 2.0, delay: 2.0, 
        options: [.repeat, .autoreverse, .curveEaseOut], 
        animations: {
        self.view.layer.position.x += 200.0
    // let's add more animations 
    // to make it more interesting!
    self.view.layer.cornerRadius = 20.0
    self.view.layer.borderWidth = 5.0
}, completion: nil)

And if you want to execute a piece of code after the animation is completed - good luck setting up your animation delegate and writing the delegate methods.

With EasyAnimation you just put your code as the completion parameter value and EasyAnimation executes it for you when your animation completes.

Spring Layer Animations

One thing I really missed since iOS9 when using CoreAnimation and CABasicAnimation was that there was no easy way to create spring animations. Luckily a handy library called RBBAnimation provides an excellent implementation of spring animations for layers - I translated the code to Swift and included RBBSpringAnimation into EasyAnimation.

Easy Animation takes care to use the new in iOS9 spring animation class CASpringAnimation when your app runs on iOS9 or higher and falls back to RBBSpringAnimation when your app runs on iOS8.

Here's how the code to create a spring animation for the layer position, transform and corner radius looks like:

EasyAnimation
    UIView.animate(duration: 2.0, delay: 0.0, 
      usingSpringWithDamping: 0.25, 
      initialSpringVelocity: 0.0, 
      options: [], 
      animations: {
        self.view.layer.position.x += 200.0
        self.view.layer.cornerRadius = 50.0
        self.view.layer.transform = CATransform3DMakeScale(1.2, 1.2, 1.0)
    }, completion: nil)

Sam Davies collaborated on the spring animations code. Thanks a ton - I couldn't have figured this one on my own!

Chain Animations

animate(duration:animations:..) is really handy but chaining one animation after another is a major pain (especially if we are talking about more than 2 animations).

EasyAnimation allows you to use a method to just chain two or more animations together. Call animateAndChain(duration:delay:options:animations:completion:) and then chain to it more animations. Use animate(duration:animations...) or any other method to create chained animations.

EasyAnimation
    UIView.animateAndChain(duration: 1.0, delay: 0.0, 
      options: [], animations: {
        self.view.center.y += 100
    }, completion: nil).animate(duration: 1.0, animations: {
        self.view.center.x += 100
    }).animate(duration: 1.0, animations: {
        self.view.center.y -= 100
    }).animate(duration: 1.0, animations: {
        self.view.center.x -= 100
    })

Yes - that works, give it a try in your project :]

This code will animate the view along a rectangular path - first downwards, then to the right, then up, then to the initial point where the animation started.

What a perfect oportunity to repeat the animation and make the animation run continuosly! Add options parameter to the last animate(duration:... in the chain and turn on the .repeat option.

This will make the whole chain (e.g. the 4 animations) repeat continuously.

If you want to pause between any two animations in the chain - just use the delay parameter and it will all just work.

Note: animateAndChain does not create a serial queue to which you could add animations at any time. You schedule your animations once with one call like the example above and it runs on its own, you can't add or remove animations to and from the sequence.

Cancel Chain Animations

If you have a repeating (or a normal) chain animation on screen you can cancel it at any time. Just grab hold of the animation object and call cancelAnimationChain on it any time you want.

let chain = UIView.animateAndChain(duration: 1.0, delay: 0.0,
    options: [], animations: {
        self.square.center.y += 100
    }, completion: nil).animate(duration: 1.0, animations: {
  [... the rest of the animations in the chain]
chain.cancelAnimationChain()

If you want to do some cleanup after the animation chain is cancelled provide a block of code to the cancelAnimationChain method:

chain.cancelAnimationChain({
  self.myView.center = initialPosition
  //etc. etc.
})

The animation will not stop immediately but once it completes the current step of the chain it will stop and cancel all scheduled animations in this chain.

Installation

  • CocoaPods: Add to your project's Podfile:

pod 'EasyAnimation'

  • Carthage: If you can help with Cartage support let me know.

  • Source code: To install with the source code - clone this repo or download the source code as a zip file. Include all files within the EasyAnimation folder into your project.

Credit

Author: Marin Todorov

More about Marin:


iOS Animations by Tutorials, Author

iOS Animations by Emails Newsletter, Author

Includes parts of RBBAnimation by Robert Böhnke. The code is translated from Objective-C to Swift by Marin Todorov.

Collaborator on the spring animation integration: Sam Davies.

License

EasyAnimation is available under the MIT license. See the LICENSE file for more info.

RBBAnimation license: https://github.com/robb/RBBAnimation/blob/master/LICENSE

To Do

  • .autoreverse for chain animations (if possible)
  • add support for keyframe animation along the path via a custom property

Version History

  • 2.0 - initialize() is deprecated so in need of manual initialization
  • 1.1 - Xcode 8
  • 1.0.5 - Xcode 7.3 compatibility
  • 1.0.4 - Swift 3 compatibility changes
  • 1.0.2 - Fixes openGL view crashes for everyone
  • 1.0.1 - Bug fixes
  • 1.0 - Swift 2.0 and iOS9
  • 0.7 - round of bug fixes and a number of improvements
  • 0.6 - first beta version
Comments
  • Non-swizzling version?

    Non-swizzling version?

    Hello!

    This library seems like an amazing tool. There's just one thing that bothers me, which is the replacing of native methods.

    Swizzling is generally not safe, and should be reserved for rare bug fixing problems.

    Is there a chance that you will have a non swizzling version?

    Maybe have an EasyAnimation class with the same static functions for animations, and a call that initiates the swizzlings for those interested?..

    Thanks!

    opened by danielgindi 14
  • Crashes on device

    Crashes on device

    Every time I try to run on the device I get the following crash:

    thread #2: tid = 0x153bbd, 0x00000001020dac90 libswiftCore.dylib`swift_unknownRelease + 24, stop reason = EXC_BAD_ACCESS (code=1, address=0x20)
        frame #0: 0x00000001020dac90 libswiftCore.dylib`swift_unknownRelease + 24
        frame #1: 0x0000000102fbd578 libswiftObjectiveC.dylib`function signature specialization <Arg[0] = Owned To Guaranteed and Exploded, Arg[1] = Dead> of ObjectiveC.Selector.init (ObjectiveC.Selector.Type)(stringLiteral : Swift.String) -> ObjectiveC.Selector + 240
        frame #2: 0x0000000102fbcb48 libswiftObjectiveC.dylib`ObjectiveC.Selector.init (ObjectiveC.Selector.Type)(stringLiteral : Swift.String) -> ObjectiveC.Selector + 20
        frame #3: 0x0000000101671e74 EasyAnimation`static ext.EasyAnimation.__ObjC.CALayer.(self=CALayer) (__ObjC.CALayer.Type)() -> () + 140 at EasyAnimation.swift:446
        frame #4: 0x0000000101671dcc EasyAnimation`static ext.EasyAnimation.__ObjC.CALayer.initialize (self=CALayer)() -> () + 132 at EasyAnimation.swift:438
        frame #5: 0x0000000101671f54 EasyAnimation`@objc static ext.EasyAnimation.__ObjC.CALayer.initialize (__ObjC.CALayer.Type)() -> () + 24 at EasyAnimation.swift:0
        frame #6: 0x00000001998fcfc8 libobjc.A.dylib`_class_initialize + 800
        frame #7: 0x00000001999038f8 libobjc.A.dylib`lookUpImpOrForward + 184
        frame #8: 0x000000019990ddb8 libobjc.A.dylib`_objc_msgSend_uncached_impcache + 56
        frame #9: 0x00000001031b6338 GPUToolsCore`DYCALayerInterposeInit() + 108
        frame #10: 0x00000001011891f0 libglInterpose.dylib`DYGLInitPlatform + 56
        frame #11: 0x00000001031a421c GPUToolsCore`GPUTools::Interpose::DYInterposeCommonInit(bool (*)(DYTransport*)) + 464
        frame #12: 0x00000001031b292c GPUToolsCore`GPUTools::Interpose::DYInterposeThreadEntry(void*) + 16
        frame #13: 0x000000019a323b28 libsystem_pthread.dylib`_pthread_body + 156
        frame #14: 0x000000019a323a8c libsystem_pthread.dylib`_pthread_start + 156
    

    It crashes here:

    private static func replaceAnimationMethods() {
        //replace actionForKey
        method_exchangeImplementations(
    ->      class_getInstanceMethod(self, "actionForKey:"),
            class_getInstanceMethod(self, "EA_actionForKey:"))
    }
    

    It works perfectly on the simulator.

    opened by rokgregoric 10
  • Sometimes Chain-Repeat Animation do not work as I expect

    Sometimes Chain-Repeat Animation do not work as I expect

    UIView.animateAndChainWithDuration(1.0, delay: 0.0, options: nil, animations: { () -> Void in
        self.layer.borderColor = flashBorderColor.CGColor
    }, completion: nil).animateWithDuration(1.0, delay: 0.0, options: UIViewAnimationOptions.Repeat, animations: { () -> Void in
        self.layer.borderColor = originBorderCGColor
    }, completion: nil)
    

    I expect it could flash borderColor, but not works for me. already read the demoApp's example, can not figure out what's going wrong here, pls help :(

    opened by kyon328 9
  • Warnings: Method 'initialize()' defines Objective-C class method 'initialize', which is not guaranteed to be invoked by Swift and will be disallowed in future versions

    Warnings: Method 'initialize()' defines Objective-C class method 'initialize', which is not guaranteed to be invoked by Swift and will be disallowed in future versions

    I get two warnings:

    Method 'initialize()' defines Objective-C class method 'initialize', which is not guaranteed to be invoked by Swift and will be disallowed in future versions

    In EasyAnimation.swift

    • line 85
    • line 148

    Xcode 8.3.1

    opened by emilpedersen 6
  • Question about

    Question about "pending:" print statements

    Hey, awesome library. I've got a low-priority question. I'm seeing this in my console when dismissing a view controller back to one of my views where I have a collection view with EasyAnimation running in the cells:

    pending: bounds from NSRect: {{0, 0}, {0, 0}} to Optional(NSRect: {{0, 0}, {414, 0}})
    pending: position from NSPoint: {0, 0} to Optional(NSPoint: {207, 1})
    pending: bounds from NSRect: {{0, 0}, {0, 0}} to Optional(NSRect: {{0, 0}, {414, 0}})
    pending: position from NSPoint: {0, 0} to Optional(NSPoint: {207, 0})
    pending: bounds from NSRect: {{0, 0}, {0, 0}} to Optional(NSRect: {{0, 0}, {8, 13}})
    pending: position from NSPoint: {0, 0} to Optional(NSPoint: {402, -0.5})
    pending: position from NSPoint: {207, 1} to Optional(NSPoint: {207, 1})
    pending: opacity from 1 to Optional(1)
    pending: bounds from NSRect: {{0, 0}, {0, 0}} to Optional(NSRect: {{0, 0}, {141.66666666666666, 253}})
    pending: position from NSPoint: {0, 0} to Optional(NSPoint: {70.833333333333329, 126.5})
    

    I am not so worried about the statements printing, but I'm unsure how to react. Does this necessarily mean I'm misusing animations in some way, or is EasyAnimation just letting me know what's going on?

    opened by sahandnayebaziz 5
  • Add an xcodeproj for Carthage support

    Add an xcodeproj for Carthage support

    Carthage uses version tags to determine what to checkout, so you'll need to tag 0.7.1 after merging to actually finish adding support. I've updated the .podspec version already.

    opened by ianyh 5
  • Unable to install via CocoaPods?

    Unable to install via CocoaPods?

    Hey Marin, I'm new to using CocoaPods so maybe I'm just doing something wrong.

    Here's my cocoapods gem setup:

    $ gem list cocoapods
    
    *** LOCAL GEMS ***
    
    cocoapods (0.38.0)
    cocoapods-core (0.38.0)
    cocoapods-downloader (0.9.1)
    cocoapods-plugins (0.4.2)
    cocoapods-stats (0.5.3)
    cocoapods-trunk (0.6.1)
    cocoapods-try (0.4.5)
    

    And here is my Podfile:

    $ cat Podfile 
    # Uncomment this line to define a global platform for your project
    platform :ios, '7.0'
    
    target 'FooApp' do
      pod 'EasyAnimation'
    end
    
    target 'FooAppTests' do
    end
    

    Finally, here is the output when I run pod install in my project:

    $ pod install
    Updating local specs repositories
    Analyzing dependencies
    [!] Unable to satisfy the following requirements:
    
    - `EasyAnimation` required by `Podfile`
    

    Any suggestions?

    opened by bitops 5
  • EasyAnimation crash in my project.

    EasyAnimation crash in my project.

    Xcode 7.1, Swift 2.0

    I installed EasyAnimation via cocoapods.

    When I launched my app, it stopped at:

    private static func replaceAnimationMethods() {
        //replace actionForKey
        method_exchangeImplementations(
            class_getInstanceMethod(self, "actionForKey:"),
            class_getInstanceMethod(self, "EA_actionForKey:"))
    }
    
    • thread #2: tid = 0x278da, 0x00000001008e6c90 libswiftCore.dylib`swift_unknownRelease + 24, stop reason = EXC_BAD_ACCESS (code=1, address=0x20)
    opened by iCodist 4
  • Animation completion will not work under some circumstances

    Animation completion will not work under some circumstances

    I need to remove all the animations on some layer under specific condition. But after I did something like this, it become impossible to add animation any more. How could I cancel all animation without hurt it?

    self.spriteLayer.removeAllAnimations()
    
    opened by iaomw 4
  • How could I chain animation from different code block?

    How could I chain animation from different code block?

    I need chain the animation from different code block while I have a var of chain. But it didn't work after the chain finished, how could I do it?

    var animationChain:EAAnimationDelayed = UIView.animateAndChainWithDuration...
    
    func someFunction() {
    
        self.animationChain.animateWithDuration...
    }
    
    func anotherFunction() {
    
        self.animationChain.animateWithDuration...
    }
    
    opened by iaomw 4
  • Getting two errors

    Getting two errors

    In the EasyAnimation.swift file I get two different error messages in "anim = RBBSpringAnimation(keyPath: pending.keyPath) if let anim = anim as? RBBSpringAnimation {"

    1. Use of unresolved identifier 'RBBSpringAnimation'
    2. Use of undeclared type 'RBBSpringAnimation'

    You have a solution for this?

    opened by KuhlTime 3
  • Use of unresolved identifier 'EAAnimationFuture'

    Use of unresolved identifier 'EAAnimationFuture'

    i'm to keep track of chains like this chains = [EAAnimationFuture]() so i can call like this. chains.map { $0.cancelAnimationChain() } but it saying Use of unresolved identifier 'EAAnimationFuture'

    opened by quickfingers 0
  • Objective c enable

    Objective c enable

    Hi, thanks for this very great library!

    However the enable() function is no more accessible from objective c while the class is marked @objc.

    Or am I missing something?

    Regards,

    opened by iDevelopper 0
  • Convenience methods

    Convenience methods

    Added a few convenience methods.

    • UIView.animateAndChain without the delay and options parameters, for brevity in situations where those parameters aren't needed.

    • EAAnimationFuture.wait - waits a specified duration before moving on to the next part of the chain.

    • EAAnimationFuture.do - executes the input block instantly without animating.

    opened by dkun7944 0
  • Animations in chain seam to get cached. Adding other animations to a view that is finished animating restars the whole chain.

    Animations in chain seam to get cached. Adding other animations to a view that is finished animating restars the whole chain.

    I used it and apparently a view that you chain animations on retains those. When you later trigger animations on the same view the previously chained animations get triggered again. Maybe there is a cleanup I don’t know about?

    Reproduce

    1. Add a view and chain some animations
    2. Animate the chain
    3. When it is finished add some other animations in code
    4. Start that animation.

    Bug The chained animations in 3 are added to the new animations. I don't feel this is the expected behaviour?

    opened by doozMen 1
Releases(2.2.1)
Owner
Marin Todorov
Co-author on "Combine: Asynchronous Programming with Swift", "RxSwift: Reactive Programming With Swift" and more
Marin Todorov
⛓ Easy to Read and Write Multi-chain Animations Lib in Objective-C and Swift.

中文介绍 This project is inspired by JHChainableAnimations! Why Choose LSAnimator & CoreAnimator? You can write complex and easy-to-maintain animations in

木子 1.6k Nov 22, 2022
Each step you take reveals a new horizon. You have taken the first step today.

The story Seeing the animations behind Paper, or the transitions behind Mail, being in a world of flat design and transitions, user interaction, app b

Ramon Gilabert 152 Nov 3, 2022
An app that will help UI/UX designers and iOS developpers to easily work together, using demos and examples about iOS capabilities, limitations, ecosystem, ...

Demoapp Work in progress... ?? What's about? It's an app built in SwiftUI that will help UI/UX designers and iOS developpers to work together smoothly

Kaww 2 Nov 2, 2022
ChainPageCollectionView A custom View with two level chained collection views and fancy transition animation

ChainPageCollectionView A custom View with two level chained collection views and fancy transition animation. Demo Requirements iOS 9.0+ Xcode 8 Insta

Yansong Li 775 Dec 7, 2022
DaisyChain is a micro framework which makes UIView animations chaining dead simple.

DaisyChain DaisyChain is a micro framework which makes UIView animations chaining dead simple. It uses the exact same interface you are familiars with

Ali Karagoz 31 Nov 3, 2022
Anima is chainable Layer-Based Animation library for Swift5.

Anima Anima is chainable Layer-Based Animation library for Swift5. It support to make sequensial and grouped animation more easily. is written as foll

Satoshi Nagasaka 528 Dec 27, 2022
(Animate CSS) animations for iOS. An easy to use library of iOS animations. As easy to use as an easy thing.

wobbly See Wobbly in action (examples) Add a drop of honey ?? to your project wobbly has a bunch of cool, fun, and easy to use iOS animations for you

Sagaya Abdulhafeez 150 Dec 23, 2021
(Animate CSS) animations for iOS. An easy to use library of iOS animations. As easy to use as an easy thing.

wobbly See Wobbly in action (examples) Add a drop of honey ?? to your project wobbly has a bunch of cool, fun, and easy to use iOS animations for you

Sagaya Abdulhafeez 150 Dec 23, 2021
null 1 Jan 26, 2022
MapTeam - A type-safe, Swift-language layer over SQLite3

SQLite.swift A type-safe, Swift-language layer over SQLite3. SQLite.swift provid

Théotime 0 Jan 18, 2022
Twinkle is a Swift and easy way to make any UIView in your iOS or tvOS app twinkle.

Twinkle ✨ Twinkle is a Swift and easy way to make any UIView in your iOS or tvOS app twinkle. This library creates several CAEmitterLayers and animate

patrick piemonte 600 Nov 24, 2022
A library of custom iOS View Controller Animations and Interactions.

RZTransitions is a library to help make iOS7 custom View Controller transitions slick and simple. Installation CocoaPods (Recommended) Add the followi

Rightpoint 1.9k Nov 20, 2022
DynamicBlurView is a dynamic and high performance UIView subclass for Blur.

DynamicBlurView DynamicBlurView is a dynamic and high performance UIView subclass for Blur. Appetize's Demo Since using the CADisplayLink, it is a hig

Kyohei Ito 929 Jan 5, 2023
UIView category that adds shake animation

UIView category that adds a shake animation like the password field of the OSX login screen. Screenshot Setup with CocoaPods Add pod 'UIView+Shake' to

Andrea Mazzini 498 Nov 20, 2022
UIView subclass that bends its edges when its position changes.

AHKBendableView BendableView is a UIView subclass that bends its edges when its position change is animated. Internally, BendableView contains CAShape

Arek Holko 591 Jul 24, 2022
A collection of animations for iOS. Simple, just add water animations.

DCAnimationKit A collection of animations for iOS Simply, just add water! DCAnimationKit is a category on UIView to make animations easy to perform. E

Dalton 797 Sep 23, 2022
Testing the new ShazamKit framework announced at WWDC 2021

ShazamKit Demo Using the ShazamKit framework announced at WWDC 2021 to perform song recognition. Demo Tweet Usage Open the project and change the Bund

Sai Kambampati 18 Mar 17, 2022
A library to simplify iOS animations in Swift.

Updated for Swift 4.2 Requires Xcode 10 and Swift 4.2. Installation Drop in the Spring folder to your Xcode project (make sure to enable "Copy items i

Meng To 14k Jan 3, 2023