Update bazel workspace to latest versions. (#40)

This increases the following versions:

- bazel from 0.11 to 0.20.0
- build_bazel_rules_apple from 7ea0557 to 0.9.0
- build_bazel_rules_swift to 0.4.0 (new)
- bazel_ios_warnings from v1.0.1 to v2.0.0
- Xcode from 8 to 9.
- Swift pinned to 3.
- Unit test upgraded to UI tests in order to resolve the following error:

```
Test Case '-[MDMAnimationTraitsSystemModalMovementTests testSystemModalMovementTimingCurveMatchesModalMovementTiming]' started.
2018-12-05 15:34:37.234 xctest[18910:576549] *** Assertion failure in Class  _Nonnull _UIStatusBarGetVisualProviderClassForScreen(UIScreen *__strong _Nonnull)(), /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKitCore_Sim/UIKit-3698.93.8/_UIStatusBarVisualProvider.m:54
Invalid connection: com.apple.coresymbolicationd
<unknown>:0: error: -[MDMAnimationTraitsSystemModalMovementTests testSystemModalMovementTimingCurveMatchesModalMovementTiming] : failed: caught "NSInternalInconsistencyException", "No status bar visual provider for screen <UIScreen: 0x7fecc1401830; bounds = {{0, 0}, {320, 480}}>"
(
	0   CoreFoundation                      0x00000001048371bb __exceptionPreprocess + 331
	1   libobjc.A.dylib                     0x0000000103ddd735 objc_exception_throw + 48
	2   CoreFoundation                      0x0000000104836f42 +[NSException raise:format:arguments:] + 98
	3   Foundation                          0x00000001037e0940 -[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:] + 166
	4   UIKitCore                           0x000000010928faae _UIStatusBarGetVisualProviderClassForScreen + 778
	5   UIKitCore                           0x00000001092a817b +[_UIStatusBar _visualProviderClass] + 62
	6   UIKitCore                           0x00000001092ad323 +[_UIStatusBar heightForOrientation:] + 27
	7   UIKitCore                           0x00000001092e6fa7 +[UIStatusBar_Modern _heightForStyle:orientation:forStatusBarFrame:] + 32
	8   UIKitCore                           0x0000000108b2cae6 -[UIViewController _defaultInitialViewFrame] + 127
	9   UIKitCore                           0x0000000108b2ce3b -[UIViewController loadView] + 272
	10  UIKitCore                           0x0000000108b2d0ee -[UIViewController loadViewIfRequired] + 175
	11  UIKitCore                           0x0000000108b2d940 -[UIViewController view] + 27
	12  UIKitCore                           0x0000000109184c53 -[UIWindow addRootViewControllerViewIfPossible] + 122
	13  UIKitCore                           0x000000010918536e -[UIWindow _setHidden:forced:] + 294
	14  UIKitCore                           0x00000001091985c0 -[UIWindow makeKeyAndVisible] + 42
	15  UnitTests                           0x000000011b470570 -[MDMAnimationTraitsSystemModalMovementTests setUp] + 496
	16  XCTest                              0x0000000103475c74 -[XCTestCase(Failures) performFailableBlock:testCaseRun:shouldInterruptTest:] + 57
	17  XCTest                              0x0000000103475b91 -[XCTestCase(Failures) _performTurningExceptionsIntoFailuresInterruptAfterHandling:block:] + 96
	18  XCTest                              0x000000010341df61 __24-[XCTestCase invokeTest]_block_invoke_3 + 89
	19  XCTest                              0x0000000103485db2 -[XCTContext _runActivityNamed:type:block:] + 304
	20  XCTest                              0x00000001034267d6 -[XCTestCase startActivityWithTitle:type:block:] + 218
	21  XCTest                              0x00000001034269b3 -[XCTestCase startActivityWithTitle:block:] + 60
	22  XCTest                              0x000000010341dadf __24-[XCTestCase invokeTest]_block_invoke + 342
	23  XCTest                              0x000000010347bb7e -[XCUITestContext performInScope:] + 248
	24  XCTest                              0x000000010341d8ce -[XCTestCase testContextPerformInScope:] + 98
	25  XCTest                              0x000000010341d97c -[XCTestCase invokeTest] + 137
	26  XCTest                              0x000000010341f4b7 __26-[XCTestCase performTest:]_block_invoke_2 + 43
	27  XCTest                              0x0000000103475c74 -[XCTestCase(Failures) performFailableBlock:testCaseRun:shouldInterruptTest:] + 57
	28  XCTest                              0x0000000103475b91 -[XCTestCase(Failures) _performTurningExceptionsIntoFailuresInterruptAfterHandling:block:] + 96
	29  XCTest                              0x000000010341f3ce __26-[XCTestCase performTest:]_block_invoke.330 + 88
	30  XCTest                              0x000000010348644b +[XCTContext runInContextForTestCase:block:] + 225
	31  XCTest                              0x000000010341eafd -[XCTestCase performTest:] + 675
	32  XCTest                              0x00000001034621a2 -[XCTest runTest] + 57
	33  XCTest                              0x0000000103419ccb __27-[XCTestSuite performTest:]_block_invoke + 365
	34  XCTest                              0x00000001034194a3 -[XCTestSuite _performProtectedSectionForTest:testSection:] + 55
	35  XCTest                              0x0000000103419766 -[XCTestSuite performTest:] + 296
	36  XCTest                              0x00000001034621a2 -[XCTest runTest] + 57
	37  XCTest                              0x0000000103419ccb __27-[XCTestSuite performTest:]_block_invoke + 365
	38  XCTest                              0x00000001034194a3 -[XCTestSuite _performProtectedSectionForTest:testSection:] + 55
	39  XCTest                              0x0000000103419766 -[XCTestSuite performTest:] + 296
	40  XCTest                              0x00000001034621a2 -[XCTest runTest] + 57
	41  XCTest                              0x0000000103419ccb __27-[XCTestSuite performTest:]_block_invoke + 365
	42  XCTest                              0x00000001034194a3 -[XCTestSuite _performProtectedSectionForTest:testSection:] + 55
	43  XCTest                              0x0000000103419766 -[XCTestSuite performTest:] + 296
	44  XCTest                              0x00000001034621a2 -[XCTest runTest] + 57
	45  XCTest                              0x0000000103491e86 __44-[XCTTestRunSession runTestsAndReturnError:]_block_invoke + 171
	46  XCTest                              0x0000000103491fa7 __44-[XCTTestRunSession runTestsAndReturnError:]_block_invoke.80 + 68
	47  XCTest                              0x0000000103431bc1 -[XCTestObservationCenter _observeTestExecutionForBlock:] + 585
	48  XCTest                              0x0000000103491bfa -[XCTTestRunSession runTestsAndReturnError:] + 623
	49  XCTest                              0x00000001033fe6b6 -[XCTestDriver runTestsAndReturnError:] + 422
	50  XCTest                              0x00000001034829cd _XCTestMain + 1478
	51  xctest                              0x00000001032eaffc main + 282
	52  libdyld.dylib                       0x0000000106899575 start + 1
	53  ???                                 0x0000000000000004 0x0 + 4
)
Test Case '-[MDMAnimationTraitsSystemModalMovementTests testSystemModalMovementTimingCurveMatchesModalMovementTiming]' failed (0.712 seconds).
Test Suite 'MDMAnimationTraitsSystemModalMovementTests' failed at 2018-12-05 15:34:37.939.
	 Executed 1 test, with 1 failure (1 unexpected) in 0.712 (0.712) seconds
```

Tested by running:

    ./.kokoro
3 files changed
tree: 234414565c9b04579ad41c34678dd2d46d57cfe1
  1. examples/
  2. img/
  3. resources/
  4. scripts/
  5. src/
  6. tests/
  7. .clang-format
  8. .codecov.yml
  9. .gitignore
  10. .jazzy.yaml
  11. .kokoro
  12. .travis.yml
  13. AUTHORS
  14. BUILD
  15. CHANGELOG.md
  16. CONTRIBUTING.md
  17. LICENSE
  18. MotionInterchange.podspec
  19. Podfile
  20. Podfile.lock
  21. README.md
  22. WORKSPACE
README.md

Motion Interchange Banner

A standard format for representing animation traits in Objective-C and Swift.

Build Status codecov CocoaPods Compatible Platform

“Magic numbers” — those lonely, abandoned values without a home — are often one of the first things targeted in code review for cleanup. And yet, numbers related to animations may go unnoticed and left behind, scattered throughout a code base with little to no organizational diligence. These forgotten metrics form the backbone of mobile interactions and are often the ones needing the most care - so why are we ok leaving them scattered throughout a code base?

// Let's play "find the magic number": how many magic numbers are hidden in this code?
[UIView animateWithDuration:0.230
                      delay:0
                      options:UIViewAnimationOptionCurveEaseOut
                      animations:^{
                        myButton.position = updatedPosition;
                      }
                      completion:nil];
// Hint: the answer is not "one, the number 0.230".

The challenge with extracting animation magic numbers is that we often don't have a clear definition of what an animation is composed of. An animation is not simply determined by its duration, in the same way that a color is not simply determined by how red it is.

The traits of an animation — like the red, green, and blue components of a color — include the following:

  • Delay.
  • Duration.
  • Timing curve.
  • Repetition.

Within this library you will find simple data types for storing and representing animation traits so that the magic numbers that define your animations can find a place to call home.

Welcome home, lost numbers.

Sibling library: Motion Animator

While it is possible to use the Motion Interchange as a standalone library, the Motion Animator is designed to be the primary consumer of Motion Interchange data types. Consider using these libraries together, with MotionAnimator as your primary dependency.

MDMAnimationTraits *animationTraits =
    [[MDMAnimationTraits alloc] initWithDuration:0.230
                              timingFunctionName:kCAMediaTimingFunctionEaseInEaseOut];

MDMMotionAnimator *animator = [[MDMMotionAnimator alloc] init];
[animator animateWithTraits:animationTraits animations:^{
  view.alpha = 0;
}];

To learn more, visit the MotionAnimator GitHub page:

https://github.com/material-motion/motion-animator-objc

Installation

Installation with CocoaPods

CocoaPods is a dependency manager for Objective-C and Swift libraries. CocoaPods automates the process of using third-party libraries in your projects. See the Getting Started guide for more information. You can install it with the following command:

gem install cocoapods

Add MotionInterchange to your Podfile:

pod 'MotionInterchange'

Then run the following command:

pod install

Usage

Import the framework:

@import MotionInterchange;

You will now have access to all of the APIs.

Example apps/unit tests

Check out a local copy of the repo to access the Catalog application by running the following commands:

git clone https://github.com/material-motion/motion-interchange-objc.git
cd motion-interchange-objc
pod install
open MotionInterchange.xcworkspace

Guides

  1. Animation traits
  2. Timing curves

Animation traits

The primary data type you'll make use of is MDMAnimationTraits. This class can store all of the necessary traits that make up an animation, including:

  • Delay.
  • Duration.
  • Timing curve.
  • Repetition.

In Objective-C, you initialize a simple ease in/out cubic bezier instance like so:

MDMAnimationTraits *traits = [[MDMAnimationTraits alloc] initWithDuration:0.5];

And in Swift:

let traits = MDMAnimationTraits(duration: 0.5)

There are many more ways to initialize animation traits. Read the header documentation to see all of the available initializers.

Timing curves

A timing curve describes how quickly an animation progresses over time. Two types of timing curves are supported by Core Animation, and therefore by the MotionInterchange:

  • Cubic bezier
  • Spring

Cubic beziers are represented by the CAMediaTimingFunction object. To define an animation trait with a cubic bezier curve in Objective-C:

CAMediaTimingFunction *timingCurve =
    [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
MDMAnimationTraits *traits =
    [[MDMAnimationTraits alloc] initWithDelay:0 duration:0.5 timingCurve:timingCurve];

And in Swift:

let timingCurve = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
let traits = MDMAnimationTraits(delay: 0, duration: 0.5, timingCurve: timingCurve)

You can also use the UIViewAnimationCurve type to initialize a timing curve in Objective-C:

MDMAnimationTraits *traits =
    [[MDMAnimationTraits alloc] initWithDuration:0.5 animationCurve:UIViewAnimationCurveEaseIn];

And in Swift:

let traits = MDMAnimationTraits(duration: 0.5, animationCurve: .easeIn)

Springs are represented with the custom MDMSpringTimingCurve type. To define an animation trait with a spring curve in Objective-C:

MDMSpringTimingCurve *timingCurve =
    [[MDMSpringTimingCurve alloc] initWithMass:1 tension:100 friction:10];
MDMAnimationTraits *traits =
    [[MDMAnimationTraits alloc] initWithDelay:0 duration:0.5 timingCurve:timingCurve];

And in Swift:

let timingCurve = MDMSpringTimingCurve(mass: 1, tension: 100, friction: 10)
let traits = MDMAnimationTraits(delay: 0, duration: 0.5, timingCurve: timingCurve)

Springs can also be initialized using UIKit's damping ratio concept. The MDMSpringTimingCurveGenerator type generates MDMSpringTimingCurve instances when needed. A spring timing curve generator can be stored as the timingCurve of an MDMAnimationTraits instance.

MDMSpringTimingCurveGenerator *timingCurve =
    [[MDMSpringTimingCurveGenerator alloc] initWithDuration:<#(NSTimeInterval)#> dampingRatio:<#(CGFloat)#>];
MDMAnimationTraits *traits =
    [[MDMAnimationTraits alloc] initWithDelay:0 duration:0.5 timingCurve:timingCurve];

And in Swift:

let timingCurve = MDMSpringTimingCurveGenerator(duration: 0.5, dampingRatio: 0.5)
let traits = MDMAnimationTraits(delay: 0, duration: 0.5, timingCurve: timingCurve)

Contributing

We welcome contributions!

Check out our upcoming milestones.

Learn more about our team, our community, and our contributor essentials.

License

Licensed under the Apache 2.0 license. See LICENSE for details.