Swiftpack.co - Package - HeroTransitions/Hero

Hero is a library for building iOS view controller transitions. It provides a declarative layer on top of the UIKit's cumbersome transition APIs—making custom transitions an easy task for developers.

Carthage compatible codecov Version License Xcode 9.0+ iOS 8.0+ Swift 4.0+ 中文 README Donate


Hero is similar to Keynote's Magic Move. It checks the heroID property on all source and destination views. Every matched view pair is then automatically transitioned from its old state to its new state.

Hero can also construct animations for unmatched views. It is easy to define these animations via the heroModifiers property. Hero will run these animations alongside the Magic Move animations. All of these animations can be interactively controlled by user gestures.

At view controller level, Hero provides several template transitions that you can set through heroModalAnimationType, heroNavigationAnimationType, and heroTabBarAnimationType. These can be used as the foundation of your custom transitions. Combine with heroID & heroModifiers to make your own unique transitions.


By default, Hero provides dynamic duration based on the Material Design Motion Guide. Duration is automatically determined by changes to distance and size—saving you the hassle, while providing consistent and delightful animations.

Hero doesn't make any assumptions about how the view is built or structured. It won't modify any of your views' states other than hiding them during the animation. This makes it work with Auto Layout, programmatic layout, UICollectionView (without modifying its layout object), UITableView, UINavigationController, UITabBarController, etc...

Example Gallery

Checkout the Example Gallery Blog Post for a general idea of what you can achieve with Hero

Usage Example 1

View Controller 1

redView.hero.id = "ironMan"
blackView.hero.id = "batMan"

View Controller 2

self.hero.isEnabled = true
redView.hero.id = "ironMan"
blackView.hero.id = "batMan"
whiteView.hero.modifiers = [.translate(y:100)]

Usage Example 2

View Controller 1

greyView.hero.id = "skyWalker"

View Controller 2

self.hero.isEnabled = true
greyView.hero.id = "skyWalker"

// collectionView is the parent view of all red cells
collectionView.hero.modifiers = [.cascade]
for cell in redCells {
    cell.hero.modifiers = [.fade, .scale(0.5)]

You can do these in the storyboard too!



Add the following entry to your Podfile:

pod 'Hero'

Then run pod install.

Don't forget to import Hero in every file you'd like to use Hero.


Add the following entry to your Cartfile:

github "HeroTransitions/Hero"

Then run carthage update.

If this is your first time using Carthage in the project, you'll need to go through some additional steps as explained over at Carthage.

Swift Package Manager

To integrate using Apple's Swift package manager, add the following as a dependency to your Package.swift:

.package(url: "https://github.com/HeroTransitions/Hero.git", .upToNextMajor(from: "1.3.0"))

and then specify "Hero" as a dependency of the Target in which you wish to use Hero. Here's an example PackageDescription:

// swift-tools-version:4.0
import PackageDescription

let package = Package(
    name: "MyPackage",
    products: [
            name: "MyPackage",
            targets: ["MyPackage"]),
    dependencies: [
        .package(url: "https://github.com/HeroTransitions/Hero.git", .upToNextMajor(from: "1.5.0"))
    targets: [
            name: "MyPackage",
            dependencies: ["Hero"])


  • Drag the Sources folder anywhere in your project.


Checkout the WIKI PAGES (Usage Guide) for documentations.

For more up-to-date ones, please see the header-doc. (use alt+click in Xcode)

Interactive Transition Tutorials

Interactive transitions with Hero (Part 1)


Not able to use Hero transition even when self.hero.isEnabled is set to true

Make sure that you have also enabled self.hero.isEnabled on the navigation controller if you are doing a push/pop inside the navigation controller.

Views being covered by another matched view during the transition

Matched views use global coordinate space while unmatched views use local coordinate space by default. Local coordinate spaced views might be covered by other global coordinate spaced views. To solve this, use the useGlobalCoordinateSpace modifier on the views being covered. Checkout Coordinate Space Wiki page for details.

Push animation is shown along side my custom animation

This is the default animation for navigation controller provided by Hero. To disable the push animation, set self.hero.navigationAnimationType to .fade or .none on the navigation controller.

How do I use a different default animation when dismissing

You can use the animation type .selectBy(presenting:dismissing) to specify a different default animation for dismiss.

For example:

    self.hero.modalAnimationType = .selectBy(presenting:.zoom, dismissing:.zoomOut)


We welcome any contributions. Please read the Contribution Guide.


Stars: 17758
Help us keep the lights on



1.5.0 - Oct 29, 2019

Maintainance Pre-Swift 5 release.

New maintainers




  • Use custom snapshot for views that implement HeroCustomSnapshotView. #541 by @ManueGE


  • Added support for right to left languages. #520 by @ManueGE

  • The hidden state of subviews are now taken into account in optimized snapshot type for UIImageView. #521 by @ManueGE


  • Fix iOS demo app failing and style on iOS 13
  • Fix lint warnings and build errors in demo app
  • Add extra metadata to podspec
  • Deprecated messages to renamed
  • Add Joe Mattiello into Podspec authors for publishing
  • Fix pod lib lint failures
  • Update Podspec imports to match source imports
  • Use more minimal import
  • Remove Swift files from framework bundle products
  • Remove access modifier warnings (#616)
  • GitIgnore xcode log files
  • Docs - Run jazzy against new spec
  • Docs - Update jazzy config
  • Bump version to 1.5.0
  • Set theme jekyll-theme-midnight
  • Use custom snapshot for views that implements HeroCustomSnapshotView (#541)
  • Keep using default navigation animation direction with RTL languages (#520)
  • Hidden subviews not taken in account in optimized snapshot type (#521)
  • Update Collection 2.0 (#553)

1.4.0 - Oct 14, 2018

This release adds support for Swift 4.2 and also maintains backward compatibility for previous Swift versions. Thank you to @rennarda for contributing to this release 🥇


1.3.1 - Sep 11, 2018

This release fixes a retain cycle caused by strong references to delegates.

Thanks to @mkieselmann for contributing to this release 👊🥇💯


  • Fixed the retain cycle caused by strong references to previousNavigationDelegate and previousTabBarDelegate. #516 by @mkieselmann

1.3.0 - Jul 30, 2018

This version fixes a few bugs related to animations and improves handling of UINavigationController delegate events and the ability to provide completion blocks for basic transition methods.

Thanks to @lkzhao, @2blane, @kartikthapar, and @bradphilips for contributing to this release 💪💯🥇


  • Adds an optional completion block parameter to the dismissViewController and replaceViewController methods. #456 by @kartikthapar


  • Allows previous UINavigationController delegate to handle delegate events. #430 by @bradphilips


  • Fixed shadows being cutoff by snapshots. #440 by @2blane
  • Fixed animation flickering on CALayer animation. f4dab9 by @lkzhao

1.2.0 - Apr 12, 2018

  • add HeroTransitionDelegate for observing transition state and progress

  • add ability to change target state during interactive transition. https://github.com/lkzhao/Hero/issues/322

    Just call the following method before calling finish(animate:) and provide the target state similar to apply(modifiers:, to:)

    Hero.shared.changeTarget(modifiers:, to:)

    for example:

    someView.hero.modifiers = [.translate(x: 100)]
    // when you want to finish interactive transition
    Hero.shared.changeTarget(modifiers:[.translate(x: -100)], to: someView)
    // this will animate someView to the state of `.translate(x: -100)` instead of `.translate(x: 100)`
  • a number of bug fixes and improvements:

    • fix 2x mode on ipad
    • Add type hinting to CascadeDirection comperator (#403) @BennX
    • Update for Xcode 9.3 and Swift 4.1 (#439) @joaomvfsantos
    • Add UIView+Hero.swift and UIViewController+Hero.swift to public heade… (#425) @DanielAsher
    • copy image view resizing filter to snapshot (#428) @sroik
    • TabBarController.selectedViewController issue (#407) @dDomovoj
    • Fix typo on 'Advanture' (#398) @fabiothiroki
    • Update README.zh-cn.md (#429) @Fidetro