Skip to content
This repository has been archived by the owner on Mar 3, 2020. It is now read-only.

keyPath property animations #274

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
141 changes: 129 additions & 12 deletions pop-tests/POPAnimationTests.mm
Expand Up @@ -26,6 +26,55 @@

using namespace POP;

@interface POPRandomPropertyGivingObject : NSObject

@property (nonatomic,assign) NSInteger number;
@property (nonatomic,assign) NSInteger secondNumber;

@end

@implementation POPRandomPropertyGivingObject

@synthesize number, secondNumber;

- (POPAnimatableProperty*)animationPropertyForNumber
{
return [POPAnimatableProperty propertyWithName:@"com.pop.tests.number" initializer:^(POPMutableAnimatableProperty *prop) {
prop.readBlock = ^(POPRandomPropertyGivingObject* obj, CGFloat values[]) {
values[0] = obj.number;
};
prop.writeBlock = ^(POPRandomPropertyGivingObject* obj, const CGFloat values[]) {
obj.number = values[0];
};
prop.threshold = 1.0;
}];
}

- (void)setValue:(id)value forKeyPath:(NSString *)keyPath
{
if ( [keyPath isEqualToString:@"number"] ) {
self.number = [value integerValue];
} else if ( [keyPath isEqualToString:@"secondNumber"] ) {
self.secondNumber = [value integerValue];
} else {
[super setValue:value forKeyPath:keyPath];
}
}

- (id)valueForKeyPath:(NSString *)keyPath
{
if ( [keyPath isEqualToString:@"number"] ) {
return @(self.number);
} else if ( [keyPath isEqualToString:@"secondNumber"] ) {
return @(self.secondNumber);
} else {
return [super valueForKeyPath:keyPath];
}
return nil;
}

@end

@interface POPAnimation (TestExtensions)
@property (strong, nonatomic) NSString *sampleKey;
@end
Expand Down Expand Up @@ -110,10 +159,10 @@ - (void)testAnimationValues
anim.roundingFactor = 1.0;

id layer = [OCMockObject niceMockForClass:[CALayer class]];
[[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([anim.fromValue CGPointValue]), Vector2r([anim.toValue CGPointValue]), 0.25).cg_point()];
[[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([anim.fromValue CGPointValue]), Vector2r([anim.toValue CGPointValue]), 0.5).cg_point()];
[[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([anim.fromValue CGPointValue]), Vector2r([anim.toValue CGPointValue]), 0.75).cg_point()];
[[layer expect] setPosition:[anim.toValue CGPointValue]];
[(CALayer*)[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([anim.fromValue CGPointValue]), Vector2r([anim.toValue CGPointValue]), 0.25).cg_point()];
[(CALayer*)[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([anim.fromValue CGPointValue]), Vector2r([anim.toValue CGPointValue]), 0.5).cg_point()];
[(CALayer*)[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([anim.fromValue CGPointValue]), Vector2r([anim.toValue CGPointValue]), 0.75).cg_point()];
[(CALayer*)[layer expect] setPosition:[anim.toValue CGPointValue]];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for updating these!


[layer pop_addAnimation:anim forKey:@"key"];
POPAnimatorRenderDuration(self.animator, self.beginTime, 1, 0.25);
Expand Down Expand Up @@ -401,8 +450,8 @@ - (void)testReuse

id layer = [OCMockObject niceMockForClass:[CALayer class]];

[[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([fromValue CGPointValue]), Vector2r([toValue CGPointValue]), testProgress).cg_point()];
[[layer expect] setPosition:[toValue CGPointValue]];
[(CALayer*)[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([fromValue CGPointValue]), Vector2r([toValue CGPointValue]), testProgress).cg_point()];
[(CALayer*)[layer expect] setPosition:[toValue CGPointValue]];

[layer pop_addAnimation:anim forKey:@"key"];

Expand All @@ -418,8 +467,8 @@ - (void)testReuse

layer = [OCMockObject niceMockForClass:[CALayer class]];

[[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([fromValue CGPointValue]), Vector2r([toValue CGPointValue]), testProgress).cg_point()];
[[layer expect] setPosition:[toValue CGPointValue]];
[(CALayer*)[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([fromValue CGPointValue]), Vector2r([toValue CGPointValue]), testProgress).cg_point()];
[(CALayer*)[layer expect] setPosition:[toValue CGPointValue]];

[layer pop_addAnimation:anim forKey:@"key"];

Expand Down Expand Up @@ -754,10 +803,10 @@ - (void)testNilKey
anim.roundingFactor = 1.0;

id layer = [OCMockObject niceMockForClass:[CALayer class]];
[[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([anim.fromValue CGPointValue]), Vector2r([anim.toValue CGPointValue]), 0.25).cg_point()];
[[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([anim.fromValue CGPointValue]), Vector2r([anim.toValue CGPointValue]), 0.5).cg_point()];
[[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([anim.fromValue CGPointValue]), Vector2r([anim.toValue CGPointValue]), 0.75).cg_point()];
[[layer expect] setPosition:[anim.toValue CGPointValue]];
[(CALayer*)[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([anim.fromValue CGPointValue]), Vector2r([anim.toValue CGPointValue]), 0.25).cg_point()];
[(CALayer*)[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([anim.fromValue CGPointValue]), Vector2r([anim.toValue CGPointValue]), 0.5).cg_point()];
[(CALayer*)[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([anim.fromValue CGPointValue]), Vector2r([anim.toValue CGPointValue]), 0.75).cg_point()];
[(CALayer*)[layer expect] setPosition:[anim.toValue CGPointValue]];

// verify nil key can be added, same as CA
[layer pop_addAnimation:anim forKey:nil];
Expand Down Expand Up @@ -888,4 +937,72 @@ - (void)testNSCopyingSupportPOPBasicAnimation
XCTAssertEqualObjects(copy.timingFunction, anim.timingFunction, @"expected equality; value1:%@ value2:%@", copy.timingFunction, anim.timingFunction);
}

- (void)testNSCopyingSupportPOPBasicAnimationWithKeyPath
{
POPBasicAnimation *anim = [POPBasicAnimation animationWithKeyPath:@"contentOffset"];

configureConcretePropertyAnimation(anim);
[self testCopyingSucceedsForConcretePropertyAnimation:anim];

anim.duration = 1.8;
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

POPBasicAnimation *copy = [anim copy];

XCTAssertEqual(copy.duration, anim.duration, @"expected equality; value1:%@ value2:%@", @(copy.duration), @(anim.duration));
XCTAssertEqualObjects(copy.timingFunction, anim.timingFunction, @"expected equality; value1:%@ value2:%@", copy.timingFunction, anim.timingFunction);
}

- (void)testAutomatedAnimatedPropertyInBasicAnimation
{
CALayer* layer = [CALayer layer];
POPBasicAnimation *anim = [POPBasicAnimation animationWithKeyPath:@"position"];
[layer pop_addAnimation:anim forKey:@"test"];
XCTAssertNotNil( anim.property, @"expected non-nil property for keyPath:%@", anim.keyPath );

anim = [POPBasicAnimation animationWithKeyPath:@"nonExistingKeyPath"];
[layer pop_addAnimation:anim forKey:@"test"];
XCTAssertNil( anim.property, @"expected nil property for keyPath:%@ (%@)", anim.keyPath, anim.property );
}

- (void)testAutomatedAnimatedPropertyInSpringAnimation
{
CALayer* layer = [CALayer layer];
POPSpringAnimation *anim = [POPSpringAnimation animationWithKeyPath:@"position"];
[layer pop_addAnimation:anim forKey:@"test"];
XCTAssertNotNil( anim.property, @"expected non-nil property for keyPath:%@", anim.keyPath );

anim = [POPSpringAnimation animationWithKeyPath:@"nonExistingKeyPath"];
[layer pop_addAnimation:anim forKey:@"test"];
XCTAssertNil( anim.property, @"expected nil property for keyPath:%@ (%@)", anim.keyPath, anim.property );
}

- (void)testAutomatedAnimatedPropertyInDecayAnimation
{
CALayer* layer = [CALayer layer];
POPDecayAnimation *anim = [POPDecayAnimation animationWithKeyPath:@"position"];
[layer pop_addAnimation:anim forKey:@"test"];
XCTAssertNotNil( anim.property, @"expected non-nil property for keyPath:%@", anim.keyPath );

anim = [POPDecayAnimation animationWithKeyPath:@"nonExistingKeyPath"];
[layer pop_addAnimation:anim forKey:@"test"];
XCTAssertNil( anim.property, @"expected nil property for keyPath:%@ (%@)", anim.keyPath, anim.property );
}

- (void)testAutomatedUserDefinedAnimatedProperty
{
POPRandomPropertyGivingObject* object = [[POPRandomPropertyGivingObject alloc] init];
POPBasicAnimation *anim = [POPBasicAnimation animationWithKeyPath:@"number"];
[object pop_addAnimation:anim forKey:@"test"];
XCTAssertNotNil( anim.property, @"expected non-nil property for keyPath:%@", anim.keyPath );
}

- (void)testAutomatedKeyValueDefinedAnimatedProperty
{
POPRandomPropertyGivingObject* object = [[POPRandomPropertyGivingObject alloc] init];
POPBasicAnimation *anim = [POPBasicAnimation animationWithKeyPath:@"secondNumber"];
[object pop_addAnimation:anim forKey:@"test"];
XCTAssertNotNil( anim.property, @"expected non-nil property for keyPath:%@", anim.keyPath );
}

@end
1 change: 1 addition & 0 deletions pop-tests/POPBaseAnimationTests.mm
Expand Up @@ -82,6 +82,7 @@ - (void)testCopyingSucceedsForConcretePropertyAnimation:(POPPropertyAnimation *)
XCTAssertEqual(copy.roundingFactor, anim.roundingFactor, @"expected equality; value1:%@ value2:%@", @(copy.roundingFactor), @(anim.roundingFactor));
XCTAssertEqual(copy.clampMode, anim.clampMode, @"expected equality; value1:%@ value2:%@", @(copy.clampMode), @(anim.clampMode));
XCTAssertEqual(copy.additive, anim.additive, @"expected equality; value1:%@ value2:%@", @(copy.additive), @(anim.additive));
XCTAssertEqualObjects(copy.keyPath, anim.keyPath, @"expected equality; value1:%@ value2:%@", copy.keyPath, anim.keyPath);
}

@end
Expand Down
24 changes: 23 additions & 1 deletion pop.xcodeproj/project.pbxproj
Expand Up @@ -192,6 +192,14 @@
ECDA0CD118C92D3900D14897 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ECC5A89D162FBD9B00F7F15C /* CoreGraphics.framework */; };
ECF01ED518C92B7F009E0AD1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC19121B162FB53A00E0CC76 /* Foundation.framework */; };
ECF01ED618C92B7F009E0AD1 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ECEED93D18C91ACF00DD95F2 /* UIKit.framework */; };
FA9A1C9F1BAA408E0050046A /* GLKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA9A1C9E1BAA408E0050046A /* GLKit.framework */; };
FA9A1CA01BAA40940050046A /* GLKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA9A1C9E1BAA408E0050046A /* GLKit.framework */; };
FA9A1CA21BAA409A0050046A /* GLKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA9A1CA11BAA409A0050046A /* GLKit.framework */; };
FA9A1CAB1BAA51F00050046A /* POPAnimatablePropertyInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = FA9A1CA91BAA51F00050046A /* POPAnimatablePropertyInternal.h */; settings = {ASSET_TAGS = (); }; };
FA9A1CAC1BAA51F00050046A /* POPAnimatablePropertyInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = FA9A1CA91BAA51F00050046A /* POPAnimatablePropertyInternal.h */; settings = {ASSET_TAGS = (); }; };
FA9A1CAD1BAA51F00050046A /* POPAnimatablePropertyInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = FA9A1CA91BAA51F00050046A /* POPAnimatablePropertyInternal.h */; settings = {ASSET_TAGS = (); }; };
FA9A1CB51BAB043E0050046A /* GLKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA9A1C9E1BAA408E0050046A /* GLKit.framework */; };
FA9A1CB61BAB04460050046A /* GLKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA9A1CA11BAA409A0050046A /* GLKit.framework */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -330,13 +338,17 @@
ECD80F1018CFD2EF00AE4303 /* POPGeometry.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = POPGeometry.mm; sourceTree = "<group>"; };
ECEED93D18C91ACF00DD95F2 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
ECF01ED318C92B7F009E0AD1 /* pop-tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "pop-tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
FA9A1C9E1BAA408E0050046A /* GLKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLKit.framework; path = System/Library/Frameworks/GLKit.framework; sourceTree = SDKROOT; };
FA9A1CA11BAA409A0050046A /* GLKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/GLKit.framework; sourceTree = DEVELOPER_DIR; };
FA9A1CA91BAA51F00050046A /* POPAnimatablePropertyInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = POPAnimatablePropertyInternal.h; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
0B6BE74419FFD3B900762101 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
FA9A1CA01BAA40940050046A /* GLKit.framework in Frameworks */,
1818937C1B3B77BB002C4A59 /* CoreImage.framework in Frameworks */,
1818937B1B3B77B7002C4A59 /* UIKit.framework in Frameworks */,
181893741B3B776B002C4A59 /* CoreFoundation.framework in Frameworks */,
Expand All @@ -350,6 +362,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
FA9A1C9F1BAA408E0050046A /* GLKit.framework in Frameworks */,
1818937A1B3B77B2002C4A59 /* CoreImage.framework in Frameworks */,
181893791B3B7785002C4A59 /* CoreGraphics.framework in Frameworks */,
181893771B3B7781002C4A59 /* CoreFoundation.framework in Frameworks */,
Expand All @@ -363,6 +376,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
FA9A1CA21BAA409A0050046A /* GLKit.framework in Frameworks */,
1836BBE41B3B7B9C0041334F /* Cocoa.framework in Frameworks */,
EC6885D418C7C44E00C6194C /* QuartzCore.framework in Frameworks */,
);
Expand All @@ -372,6 +386,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
FA9A1CB61BAB04460050046A /* GLKit.framework in Frameworks */,
EC7E31B518C9422F00B38170 /* pop.framework in Frameworks */,
EC7E31B418C9422600B38170 /* QuartzCore.framework in Frameworks */,
ADE1BB0636F940EC8EA7EE57 /* libPods-pop-tests-osx.a in Frameworks */,
Expand All @@ -382,6 +397,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
FA9A1CB51BAB043E0050046A /* GLKit.framework in Frameworks */,
ECDA0CD118C92D3900D14897 /* CoreGraphics.framework in Frameworks */,
ECDA0CD018C92C4C00D14897 /* libpop.a in Frameworks */,
ECDA0CCF18C92C3E00D14897 /* QuartzCore.framework in Frameworks */,
Expand Down Expand Up @@ -443,6 +459,8 @@
EC19121A162FB53A00E0CC76 /* Frameworks */ = {
isa = PBXGroup;
children = (
FA9A1CA11BAA409A0050046A /* GLKit.framework */,
FA9A1C9E1BAA408E0050046A /* GLKit.framework */,
1836BBE31B3B7B9C0041334F /* Cocoa.framework */,
181893731B3B776B002C4A59 /* CoreFoundation.framework */,
0B6BE7E619FFD98100762101 /* CoreImage.framework */,
Expand Down Expand Up @@ -577,6 +595,7 @@
EC8F017318FFC4CB00DF8905 /* Engine */ = {
isa = PBXGroup;
children = (
FA9A1CA91BAA51F00050046A /* POPAnimatablePropertyInternal.h */,
EC19128E162FB5B700E0CC76 /* POPAnimatableProperty.h */,
EC19128F162FB5B700E0CC76 /* POPAnimatableProperty.mm */,
EC9997531756A0C300A73F49 /* POPAnimationEvent.h */,
Expand Down Expand Up @@ -678,6 +697,7 @@
0B6BE77119FFD46F00762101 /* POPAnimatorPrivate.h in Headers */,
0B6BE77019FFD46600762101 /* POPLayerExtras.h in Headers */,
0B6BE76F19FFD44000762101 /* POPSpringAnimation.h in Headers */,
FA9A1CAC1BAA51F00050046A /* POPAnimatablePropertyInternal.h in Headers */,
0B6BE76E19FFD43800762101 /* POPCustomAnimation.h in Headers */,
0B6BE76D19FFD42700762101 /* POPAnimationExtras.h in Headers */,
0B6BE76C19FFD41D00762101 /* POPDecayAnimation.h in Headers */,
Expand All @@ -700,6 +720,7 @@
EC191299162FB5EC00E0CC76 /* POPAnimatableProperty.h in Headers */,
EC8F014F18FFBD3E00DF8905 /* POPBasicAnimation.h in Headers */,
EC8F014018FFBBD300DF8905 /* POPPropertyAnimation.h in Headers */,
FA9A1CAB1BAA51F00050046A /* POPAnimatablePropertyInternal.h in Headers */,
EC191296162FB5EC00E0CC76 /* POPAnimationInternal.h in Headers */,
EC191298162FB5EC00E0CC76 /* POPAnimatorPrivate.h in Headers */,
ECCBC57217D96DBD00C69976 /* FloatConversion.h in Headers */,
Expand Down Expand Up @@ -740,6 +761,7 @@
EC6885C818C7BD5F00C6194C /* POPLayerExtras.h in Headers */,
EC8F015018FFBD3E00DF8905 /* POPBasicAnimation.h in Headers */,
EC8F014118FFBBD300DF8905 /* POPPropertyAnimation.h in Headers */,
FA9A1CAD1BAA51F00050046A /* POPAnimatablePropertyInternal.h in Headers */,
EC6885BB18C7BD3700C6194C /* POPMath.h in Headers */,
EC6885C418C7BD5100C6194C /* POPAnimatorPrivate.h in Headers */,
EC6885C518C7BD5500C6194C /* POPCustomAnimation.h in Headers */,
Expand Down Expand Up @@ -872,7 +894,7 @@
isa = PBXProject;
attributes = {
LastTestingUpgradeCheck = 0700;
LastUpgradeCheck = 0640;
LastUpgradeCheck = 0700;
ORGANIZATIONNAME = Facebook;
TargetAttributes = {
0B6BE74719FFD3B900762101 = {
Expand Down
13 changes: 8 additions & 5 deletions pop.xcodeproj/xcshareddata/xcschemes/pop-ios-framework.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0640"
LastUpgradeVersion = "0700"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand All @@ -23,10 +23,10 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
Expand All @@ -48,15 +48,18 @@
ReferencedContainer = "container:pop.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
Expand All @@ -71,10 +74,10 @@
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
Expand Down