Commit 21a473d7 by Daniel Dahan

rework: adding MotionController and base classes

parent f371f1db
...@@ -10,18 +10,24 @@ ...@@ -10,18 +10,24 @@
961409AA1E43CF1B00E7BA99 /* Motion+Obj-C.swift in Sources */ = {isa = PBXBuildFile; fileRef = 961409A91E43CF1B00E7BA99 /* Motion+Obj-C.swift */; }; 961409AA1E43CF1B00E7BA99 /* Motion+Obj-C.swift in Sources */ = {isa = PBXBuildFile; fileRef = 961409A91E43CF1B00E7BA99 /* Motion+Obj-C.swift */; };
961409B61E43D17200E7BA99 /* Motion+Obj-C.swift in Headers */ = {isa = PBXBuildFile; fileRef = 961409A91E43CF1B00E7BA99 /* Motion+Obj-C.swift */; settings = {ATTRIBUTES = (Public, ); }; }; 961409B61E43D17200E7BA99 /* Motion+Obj-C.swift in Headers */ = {isa = PBXBuildFile; fileRef = 961409A91E43CF1B00E7BA99 /* Motion+Obj-C.swift */; settings = {ATTRIBUTES = (Public, ); }; };
961409B81E43D21300E7BA99 /* Motion.h in Headers */ = {isa = PBXBuildFile; fileRef = 96C98DED1E438A5700B22906 /* Motion.h */; settings = {ATTRIBUTES = (Public, ); }; }; 961409B81E43D21300E7BA99 /* Motion.h in Headers */ = {isa = PBXBuildFile; fileRef = 96C98DED1E438A5700B22906 /* Motion.h */; settings = {ATTRIBUTES = (Public, ); }; };
96BFC1701E63C3460075DE1F /* Motion.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96C98DE31E4382B100B22906 /* Motion.swift */; settings = {ATTRIBUTES = (Public, ); }; }; 9657A6AC1EDA1601004461DE /* MotionObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9657A6AB1EDA1601004461DE /* MotionObserver.swift */; };
96C98DE41E4382B100B22906 /* Motion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C98DE31E4382B100B22906 /* Motion.swift */; }; 9657A6AE1EDA19D8004461DE /* MotionAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9657A6AD1EDA19D8004461DE /* MotionAnimator.swift */; };
9657A6B31EDA63FC004461DE /* MotionContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9657A6B21EDA63FC004461DE /* MotionContext.swift */; };
96BFC1701E63C3460075DE1F /* MotionController.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96C98DE31E4382B100B22906 /* MotionController.swift */; settings = {ATTRIBUTES = (Public, ); }; };
96C98DE41E4382B100B22906 /* MotionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C98DE31E4382B100B22906 /* MotionController.swift */; };
96C98DE61E43848500B22906 /* MotionAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C98DE51E43848500B22906 /* MotionAnimation.swift */; }; 96C98DE61E43848500B22906 /* MotionAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C98DE51E43848500B22906 /* MotionAnimation.swift */; };
96C98DEB1E4389BE00B22906 /* MotionAnimation.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96C98DE51E43848500B22906 /* MotionAnimation.swift */; settings = {ATTRIBUTES = (Public, ); }; }; 96C98DEB1E4389BE00B22906 /* MotionAnimation.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96C98DE51E43848500B22906 /* MotionAnimation.swift */; settings = {ATTRIBUTES = (Public, ); }; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
961409A91E43CF1B00E7BA99 /* Motion+Obj-C.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Motion+Obj-C.swift"; sourceTree = "<group>"; }; 961409A91E43CF1B00E7BA99 /* Motion+Obj-C.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Motion+Obj-C.swift"; sourceTree = "<group>"; };
9657A6AB1EDA1601004461DE /* MotionObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionObserver.swift; sourceTree = "<group>"; };
9657A6AD1EDA19D8004461DE /* MotionAnimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionAnimator.swift; sourceTree = "<group>"; };
9657A6B21EDA63FC004461DE /* MotionContext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionContext.swift; sourceTree = "<group>"; };
96C98DD11E424AB000B22906 /* Motion.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Motion.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 96C98DD11E424AB000B22906 /* Motion.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Motion.framework; sourceTree = BUILT_PRODUCTS_DIR; };
96C98DDD1E424B9000B22906 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 96C98DDD1E424B9000B22906 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
96C98DE21E43809D00B22906 /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; }; 96C98DE21E43809D00B22906 /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
96C98DE31E4382B100B22906 /* Motion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Motion.swift; sourceTree = "<group>"; }; 96C98DE31E4382B100B22906 /* MotionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionController.swift; sourceTree = "<group>"; };
96C98DE51E43848500B22906 /* MotionAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionAnimation.swift; sourceTree = "<group>"; }; 96C98DE51E43848500B22906 /* MotionAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionAnimation.swift; sourceTree = "<group>"; };
96C98DED1E438A5700B22906 /* Motion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Motion.h; sourceTree = "<group>"; }; 96C98DED1E438A5700B22906 /* Motion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Motion.h; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
...@@ -59,7 +65,10 @@ ...@@ -59,7 +65,10 @@
96C98DE21E43809D00B22906 /* LICENSE */, 96C98DE21E43809D00B22906 /* LICENSE */,
96C98DDD1E424B9000B22906 /* Info.plist */, 96C98DDD1E424B9000B22906 /* Info.plist */,
96C98DED1E438A5700B22906 /* Motion.h */, 96C98DED1E438A5700B22906 /* Motion.h */,
96C98DE31E4382B100B22906 /* Motion.swift */, 96C98DE31E4382B100B22906 /* MotionController.swift */,
9657A6AB1EDA1601004461DE /* MotionObserver.swift */,
9657A6B21EDA63FC004461DE /* MotionContext.swift */,
9657A6AD1EDA19D8004461DE /* MotionAnimator.swift */,
96C98DE51E43848500B22906 /* MotionAnimation.swift */, 96C98DE51E43848500B22906 /* MotionAnimation.swift */,
961409A91E43CF1B00E7BA99 /* Motion+Obj-C.swift */, 961409A91E43CF1B00E7BA99 /* Motion+Obj-C.swift */,
); );
...@@ -75,7 +84,7 @@ ...@@ -75,7 +84,7 @@
files = ( files = (
961409B81E43D21300E7BA99 /* Motion.h in Headers */, 961409B81E43D21300E7BA99 /* Motion.h in Headers */,
961409B61E43D17200E7BA99 /* Motion+Obj-C.swift in Headers */, 961409B61E43D17200E7BA99 /* Motion+Obj-C.swift in Headers */,
96BFC1701E63C3460075DE1F /* Motion.swift in Headers */, 96BFC1701E63C3460075DE1F /* MotionController.swift in Headers */,
96C98DEB1E4389BE00B22906 /* MotionAnimation.swift in Headers */, 96C98DEB1E4389BE00B22906 /* MotionAnimation.swift in Headers */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
...@@ -150,8 +159,11 @@ ...@@ -150,8 +159,11 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
96C98DE61E43848500B22906 /* MotionAnimation.swift in Sources */, 96C98DE61E43848500B22906 /* MotionAnimation.swift in Sources */,
9657A6AE1EDA19D8004461DE /* MotionAnimator.swift in Sources */,
9657A6AC1EDA1601004461DE /* MotionObserver.swift in Sources */,
9657A6B31EDA63FC004461DE /* MotionContext.swift in Sources */,
961409AA1E43CF1B00E7BA99 /* Motion+Obj-C.swift in Sources */, 961409AA1E43CF1B00E7BA99 /* Motion+Obj-C.swift in Sources */,
96C98DE41E4382B100B22906 /* Motion.swift in Sources */, 96C98DE41E4382B100B22906 /* MotionController.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
......
...@@ -28,30 +28,32 @@ ...@@ -28,30 +28,32 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/** internal struct AssociatedObject {
Gets the Obj-C reference for the instance object within the UIView extension. /**
- Parameter base: Base object. Gets the Obj-C reference for the instance object within the UIView extension.
- Parameter key: Memory key pointer. - Parameter base: Base object.
- Parameter initializer: Object initializer. - Parameter key: Memory key pointer.
- Returns: The associated reference for the initializer object. - Parameter initializer: Object initializer.
*/ - Returns: The associated reference for the initializer object.
internal func AssociatedObject<T: Any>(base: Any, key: UnsafePointer<UInt8>, initializer: () -> T) -> T { */
if let v = objc_getAssociatedObject(base, key) as? T { public static func get<T: Any>(base: Any, key: UnsafePointer<UInt8>, initializer: () -> T) -> T {
if let v = objc_getAssociatedObject(base, key) as? T {
return v
}
let v = initializer()
objc_setAssociatedObject(base, key, v, .OBJC_ASSOCIATION_RETAIN)
return v return v
} }
let v = initializer() /**
objc_setAssociatedObject(base, key, v, .OBJC_ASSOCIATION_RETAIN) Sets the Obj-C reference for the instance object within the UIView extension.
return v - Parameter base: Base object.
} - Parameter key: Memory key pointer.
- Parameter value: The object instance to set for the associated object.
/** - Returns: The associated reference for the initializer object.
Sets the Obj-C reference for the instance object within the UIView extension. */
- Parameter base: Base object. public static func set<T: Any>(base: Any, key: UnsafePointer<UInt8>, value: T) {
- Parameter key: Memory key pointer. objc_setAssociatedObject(base, key, value, .OBJC_ASSOCIATION_RETAIN)
- Parameter value: The object instance to set for the associated object. }
- Returns: The associated reference for the initializer object.
*/
internal func AssociateObject<T: Any>(base: Any, key: UnsafePointer<UInt8>, value: T) {
objc_setAssociatedObject(base, key, value, .OBJC_ASSOCIATION_RETAIN)
} }
/*
* Copyright (C) 2015 - 2017, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.com>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of CosmicMind nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import UIKit
public protocol MotionAnimator: class {
/// A reference to a MotionContext.
weak var context: MotionContext! { get set }
/**
*/
func canAnimate(view: UIView, isAppearing: Bool) -> Bool
/**
*/
func animate(fromViews: [UIView], toViews: [UIView]) -> TimeInterval
/**
*/
func seekTo(elapsedTime: TimeInterval)
/**
*/
func resume(elapsedTime: TimeInterval, isReversed: Bool) -> TimeInterval
///
func clean()
}
/*
* Copyright (C) 2015 - 2017, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.com>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of CosmicMind nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import UIKit
open class MotionContext {
}
/*
* Copyright (C) 2015 - 2017, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.com>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of CosmicMind nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import UIKit
open class MotionController: NSObject, MotionSubscriber {
/// An optional reference to the animation display link.
fileprivate var displayLink: CADisplayLink? {
willSet {
guard let v = displayLink else {
return
}
v.isPaused = true
v.remove(from: RunLoop.main, forMode: RunLoopMode(rawValue: RunLoopMode.commonModes.rawValue))
}
didSet {
guard let v = displayLink else {
return
}
v.add(to: RunLoop.main, forMode: RunLoopMode(rawValue: RunLoopMode.commonModes.rawValue))
}
}
/// A reference to the animation duration.
fileprivate var animationDuration: TimeInterval = 0
/**
A reference to the animation total duration,
which is the total running animation time.
*/
fileprivate var animationTotalDuration: TimeInterval = 0
/// A reference to the animation start time.
fileprivate var animationStartTime: TimeInterval? {
didSet {
guard nil != animationStartTime else {
displayLink = nil
return
}
guard nil == displayLink else {
return
}
displayLink = CADisplayLink(target: self, selector: #selector(handleDisplayLinkUpdate(displayLink:)))
}
}
/// A reference to the animation elapsed time.
open fileprivate(set) var animationElapsedTime: TimeInterval = 0 {
didSet {
guard isTransitioning else {
return
}
updateMotionObservers()
updateMotionAnimators()
}
}
/// A reference to an Array of MotionObservers.
open fileprivate(set) var observers = [MotionObserver]()
/// A reference to an Array of MotionAnimators.
open fileprivate(set) var animators = [MotionAnimator]()
/// A boolean indicating if a transition is in progress.
open var isTransitioning: Bool {
return nil == transitionContainer
}
/// A boolean indicating if the animation is finished.
open fileprivate(set) var isFinished = false
/// A boolean indicating if the animation is interactive.
open var isInteractive: Bool {
return nil == displayLink
}
/// UIKit's supplied transition container.
open fileprivate(set) var transitionContainer: UIView!
}
extension MotionController {
/**
Handles the animation update for the display link.
- Parameter displayLink: A CADisplayLink.animation
*/
@objc
fileprivate func handleDisplayLinkUpdate(displayLink: CADisplayLink) {
guard isTransitioning else {
return
}
guard 0 < animationDuration else {
return
}
guard let v = animationStartTime else {
return
}
var elapsedTime = CACurrentMediaTime() - v
if elapsedTime > animationDuration {
animationElapsedTime = isFinished ? 1 : 0
completeTransition()
} else {
elapsedTime = elapsedTime / animationDuration
if !isFinished {
elapsedTime = 1 - elapsedTime
}
animationElapsedTime = max(0, min(1, elapsedTime))
}
}
}
extension MotionController {
fileprivate func updateMotionObservers() {
for v in observers {
v.update(elapsedTime: animationElapsedTime)
}
}
/// Updates the motion animators.
fileprivate func updateMotionAnimators() {
let elapsedTime = animationElapsedTime * animationTotalDuration
for v in animators {
v.seekTo(elapsedTime: elapsedTime)
}
}
}
extension MotionController {
/// Completes the transition.
fileprivate func completeTransition() {
cleanMotionAnimators()
cleanTransitionValues()
}
/// Cleans the motion animators Array.
fileprivate func cleanMotionAnimators() {
for v in animators {
v.clean()
}
}
/// Cleans the transition values.
fileprivate func cleanTransitionValues() {
animationStartTime = nil
}
}
/*
* Copyright (C) 2015 - 2017, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.com>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of CosmicMind nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import UIKit
public protocol MotionObserver {
/**
An update method called when an animation elapsed time is updated
during a transition.
- Parameter elapsedTime: A TimeInterval.
*/
func update(elapsedTime: TimeInterval)
}
public protocol MotionSubscriber {
/// A reference to an Array of MotionObservers.
var observers: [MotionObserver] { get }
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment