forked from Zero-zhou/iOS-Extensions
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathContinuousValuesGenerator.swift
153 lines (113 loc) · 4.91 KB
/
ContinuousValuesGenerator.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
//
// ContinuousValuesGenerator.swift
//
// Created by Augus on 6/29/16.
// Copyright © 2016 iAugus. All rights reserved.
//
import Foundation
class ContinuousValuesGenerator<T: Arithmetic> {
fileprivate var currentValue: T
/// Animated Value Generator
///
/// - parameter startValue: start value
/// - parameter endValue: end value
/// - parameter offsetPerTime: offset per time. Positive / Negative number makes no matter !!
/// - parameter generatedValue: new generated nember per time
/// - parameter completion: completion closure
@discardableResult
init(startValue: T, endValue: T, offsetPerTime: T, generatedValue: ((T) -> ()), completion: Closure? = nil) {
currentValue = startValue
let totalOffset = (endValue - startValue).double
guard abs(totalOffset) > abs(offsetPerTime.double) else {
generatedValue(endValue)
completion?()
return
}
let realOffsetPerTime = T(totalOffset > 0 ? abs(offsetPerTime.double) : -abs(offsetPerTime.double))
run(start: startValue, end: endValue, offset: realOffsetPerTime, generated: generatedValue, completion: completion)
}
// recursion
fileprivate func run(start: T, end: T, offset: T, generated: ((T) -> ()), completion: Closure? = nil) {
guard (offset.double > 0) ? currentValue < end : currentValue > end else {
if currentValue != end { generated(end) }
completion?()
return
}
currentValue += offset
generated(currentValue)
run(start: currentValue, end: end, offset: offset, generated: generated, completion: completion)
}
}
class ContinuousValuesGeneratorWithDuration<T: Arithmetic> {
fileprivate var times: Int
fileprivate var startValue: T
fileprivate var endValue: T
fileprivate var offsetPerTime: T
fileprivate var completionHandler: Closure?
fileprivate var generatedValueHandler: ((T) -> ())
/// Animated Value Generator
///
/// - parameter duration: duration time
/// - parameter startValue: start value
/// - parameter endValue: end value
/// - parameter offsetPerTime: offset per time. Positive / Negative number makes no matter !!
/// - parameter generatedValue: new generated nember per time
/// - parameter completion: completion closure
@discardableResult
init(_ duration: TimeInterval, startValue: T, endValue: T, offsetPerTime: T, generatedValue: @escaping ((T) -> ()), completion: Closure? = nil) {
let times = (endValue - startValue) / offsetPerTime
self.times = abs(times.int)
self.startValue = startValue
self.endValue = endValue
self.offsetPerTime = times.int >= 0 ? offsetPerTime : -offsetPerTime
self.generatedValueHandler = generatedValue
if self.times < 1 {
generatedValue(endValue)
completion?()
#if DEBUG
print("Animated Value Generator: Only executed once")
#endif
return
}
// let tempTotalTimes = self.times
let interval = duration / Double(self.times)
// #if DEBUG
// let note = endValue.double != 0 && endValue.double < 0.0001 ? " (Attention: About 0)" : ""
// print("\n" + "########### Animated Value Generator #############" + "\n")
// print("Start value: \(startValue)")
// print("End value: \(endValue)" + note)
// print("Offset per time: \(self.offsetPerTime)")
// print("Duration: \(duration)")
// print("Interval: \(interval)")
// print("Total times: \(tempTotalTimes)")
// print("\n" + "########### Animated Value Generator #############" + "\n")
// #endif
Timer.scheduledTimer(timeInterval: interval, target: self, selector: #selector(run(_:)), userInfo: nil, repeats: true).fire()
completionHandler = completion
}
@objc fileprivate func run(_ timer: Timer) {
// #if DEBUG
//
// let output: (T) -> () = {
// print("Animated Value Generator - Current Value: \($0)")
// }
//
// output(startValue)
//
// #endif
guard times > 0 else {
timer.invalidate()
if startValue != endValue {
generatedValueHandler(endValue)
// #if DEBUG
// output(endValue)
// #endif
}
completionHandler?()
return
}
startValue += offsetPerTime
generatedValueHandler(startValue)
times -= 1
}
}