Skip to content
This repository was archived by the owner on Dec 5, 2019. It is now read-only.

Commit 7aba788

Browse files
committed
Add animateEach operator
1 parent 7fc5abd commit 7aba788

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed

ReactiveAnimation/Animation.swift

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,98 @@
1616
public typealias AnimationCurveRawValue = UIViewAnimationCurve.RawValue
1717
#endif
1818

19+
import ReactiveCocoa
20+
21+
/// Creates an animated SignalProducer for each value that arrives on
22+
/// `producer`.
23+
///
24+
/// The `JoinStrategy` used on the inner producers will hint to
25+
/// ReactiveAnimation whether the animations should be interruptible:
26+
///
27+
/// - `Concat` will result in new animations only beginning after all previous
28+
/// animations have completed.
29+
/// - `Merge` or `Latest` will start new animations as soon as possible, and
30+
/// use the current (in progress) UI state for animating.
31+
///
32+
/// These animation behaviors are only a hint, and the framework may not be able
33+
/// to satisfy them.
34+
///
35+
/// However the inner producers are joined, binding the resulting stream of
36+
/// values to a view property will result in those value changes being
37+
/// automatically animated.
38+
///
39+
/// To delay an animation, use delay() or throttle() _before_ this function.
40+
/// Because the aforementioned operators delay delivery of `Next` events,
41+
/// applying them _after_ this function may cause values to be delivered outside
42+
/// of any animation block.
43+
///
44+
/// Examples
45+
///
46+
/// RAN(self.textField).alpha <~ alphaValues
47+
/// |> animateEach(duration: 0.2)
48+
/// /* Animate alpha without interruption. */
49+
/// |> join(.Concat)
50+
///
51+
/// RAN(self.button).alpha <~ alphaValues
52+
/// /* Delay animations by 0.1 seconds. */
53+
/// |> delay(0.1)
54+
/// |> animateEach(curve: .Linear)
55+
/// /* Animate alpha, and interrupt for new animations. */
56+
/// |> join(.Latest)
57+
///
58+
/// Returns a signal of signals, where each inner signal sends one `next`
59+
/// that corresponds to a value from the receiver, then completes when the
60+
/// animation corresponding to that value has finished. Deferring the events of
61+
/// the returned signal or having them delivered on another thread is considered
62+
/// undefined behavior.
63+
public func animateEach<T, Error>(duration: NSTimeInterval? = nil, curve: AnimationCurve = .Default)(producer: SignalProducer<T, Error>) -> SignalProducer<SignalProducer<T, NoError>, Error> {
64+
return producer |> map { value in
65+
return SignalProducer { observer, disposable in
66+
OSAtomicIncrement32(&runningInAnimationCount)
67+
disposable.addDisposable {
68+
OSAtomicDecrement32(&runningInAnimationCount)
69+
}
70+
71+
#if os(OSX)
72+
NSAnimationContext.runAnimationGroup({ context in
73+
if let duration = duration {
74+
context.duration = duration
75+
}
76+
77+
if curve != .Default {
78+
context.timingFunction = CAMediaTimingFunction(name: curve.mediaTimingFunction)
79+
}
80+
81+
sendNext(observer, value)
82+
}, completionHandler: {
83+
// Avoids weird AppKit deadlocks when interrupting an
84+
// existing animation.
85+
UIScheduler().schedule {
86+
sendCompleted(observer)
87+
}
88+
})
89+
#elseif os(iOS)
90+
var options = UIViewAnimationOptions(UInt(curve.rawValue))
91+
options |= UIViewAnimationOptions.LayoutSubviews
92+
options |= UIViewAnimationOptions.BeginFromCurrentState
93+
if curve != .Default {
94+
options |= UIViewAnimationOptions.OverrideInheritedCurve
95+
}
96+
97+
UIView.animateWithDuration(duration ?? 0.2, delay: 0, options: options, animations: {
98+
sendNext(observer, value)
99+
}, completion: { finished in
100+
if finished {
101+
sendCompleted(observer)
102+
} else {
103+
sendInterrupted(observer)
104+
}
105+
})
106+
#endif
107+
}
108+
}
109+
}
110+
19111
/// The number of animated signals in the call stack.
20112
///
21113
/// This variable should be manipulated with OSAtomic functions.

0 commit comments

Comments
 (0)