diff --git a/Cartfile b/Cartfile index 2bfea98..c517d21 100644 --- a/Cartfile +++ b/Cartfile @@ -1 +1,2 @@ -github "mxcl/PromiseKit" ~> 6.0 +#github "mxcl/PromiseKit" ~> 6.0 +github "dougzilla32/PromiseKit" "CoreCancel" diff --git a/Cartfile.resolved b/Cartfile.resolved index 8d4fefc..80a4000 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1 +1 @@ -github "mxcl/PromiseKit" "6.3.4" +github "dougzilla32/PromiseKit" "087b3cf470890ff9ea841212e2f3e285fecf3988" diff --git a/PMKUIKit.xcodeproj/project.pbxproj b/PMKUIKit.xcodeproj/project.pbxproj index fff1565..8c228e8 100644 --- a/PMKUIKit.xcodeproj/project.pbxproj +++ b/PMKUIKit.xcodeproj/project.pbxproj @@ -25,6 +25,7 @@ 63C9C4581D5D339B00101ECE /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 630B2DF51D5D0AD400DC10E9 /* Default-568h@2x.png */; }; 63C9C45E1D5D341600101ECE /* PMKUIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63C7FFA71D5BEE09003BAE60 /* PMKUIKit.framework */; }; 63C9C45F1D5D341600101ECE /* PMKUIKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 63C7FFA71D5BEE09003BAE60 /* PMKUIKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 911E6FC620F571F7006F49B9 /* TestUIViewPropertyAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 911E6FC520F571F7006F49B9 /* TestUIViewPropertyAnimator.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -95,6 +96,7 @@ 63C9C4451D5D334700101ECE /* PMKTestsHost.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PMKTestsHost.app; sourceTree = BUILT_PRODUCTS_DIR; }; 63CCF8121D5C0C4E00503216 /* Cartfile */ = {isa = PBXFileReference; lastKnownFileType = text; path = Cartfile; sourceTree = ""; }; 63CCF8171D5C11B500503216 /* Carthage.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Carthage.xcconfig; sourceTree = ""; }; + 911E6FC520F571F7006F49B9 /* TestUIViewPropertyAnimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestUIViewPropertyAnimator.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -186,6 +188,7 @@ 637E2C8E1D5C2E720043E370 /* TestUIImagePickerController.swift */, 637E2C8F1D5C2E720043E370 /* TestUIViewController.m */, 6332142A1D83CD17009F67CE /* TestUIView.swift */, + 911E6FC520F571F7006F49B9 /* TestUIViewPropertyAnimator.swift */, 637E2C9A1D5C2F600043E370 /* infrastructure.swift */, ); path = Tests; @@ -402,6 +405,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 911E6FC620F571F7006F49B9 /* TestUIViewPropertyAnimator.swift in Sources */, 637E2C951D5C2E720043E370 /* TestUIImagePickerController.swift in Sources */, 637E2C961D5C2E720043E370 /* TestUIViewController.m in Sources */, 637E2C9B1D5C2F600043E370 /* infrastructure.swift in Sources */, diff --git a/Sources/UIViewPropertyAnimator+Promise.swift b/Sources/UIViewPropertyAnimator+Promise.swift index 34ee140..b86e76a 100644 --- a/Sources/UIViewPropertyAnimator+Promise.swift +++ b/Sources/UIViewPropertyAnimator+Promise.swift @@ -5,10 +5,23 @@ import UIKit @available(iOS 10, tvOS 10, *) public extension UIViewPropertyAnimator { + /// - Note: cancelling this promise will cancel the underlying task + /// - SeeAlso: [Cancellation](http://promisekit.org/docs/) func startAnimation(_: PMKNamespacer) -> Guarantee { - return Guarantee { + return Guarantee(cancellableTask: self) { addCompletion($0) startAnimation() } } } + +@available(iOS 10, tvOS 10, *) +extension UIViewPropertyAnimator: CancellableTask { + public func cancel() { + stopAnimation(true) + } + + public var isCancelled: Bool { + return (state == .inactive) && (fractionComplete < 1.0) + } +} diff --git a/Tests/TestUIViewPropertyAnimator.swift b/Tests/TestUIViewPropertyAnimator.swift new file mode 100644 index 0000000..0902d86 --- /dev/null +++ b/Tests/TestUIViewPropertyAnimator.swift @@ -0,0 +1,46 @@ +import PromiseKit +import PMKUIKit +import XCTest +import UIKit + +@available(iOS 10, tvOS 10, *) +class UIViewPropertyAnimatorTests: XCTestCase { + func test() { + let ex1 = expectation(description: "") + let ex2 = expectation(description: "") + + let animator = UIViewPropertyAnimator(duration: 0.1, curve: .easeIn, animations: { [weak self] in + ex1.fulfill() + }) + animator.startAnimation(.promise).done { _ in + ex2.fulfill() + } + + waitForExpectations(timeout: 1) + } +} + +//////////////////////////////////////////////////////////// Cancellation + +@available(iOS 10, tvOS 10, *) +extension UIViewPropertyAnimatorTests { + func testCancel() { + let ex1 = expectation(description: "") + let ex2 = expectation(description: "") + + let animator = UIViewPropertyAnimator(duration: 0.1, curve: .easeIn, animations: { [weak self] in + ex1.fulfill() + }) + let p = cancellable(animator.startAnimation(.promise)).done { _ in + XCTFail() + }.catch(policy: .allErrors) { error in + error.isCancelled ? ex2.fulfill() : XCTFail("Error: \(error)") + } + p.cancel() + + XCTAssert(animator.isCancelled) + XCTAssert(p.isCancelled) + + waitForExpectations(timeout: 1) + } +}