rm-extensions 0.3.2 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/motion/util.rb +118 -0
- data/lib/rm-extensions/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4638058073ecd449cd49a4ae5d0b2c0bcea20304
|
4
|
+
data.tar.gz: fda67c1392046c93f1c7de0c6de830cf68cd733b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d78724ff4f31f6014c7dc9732cc3a6a80919f3ccc38c0abc2668f51eb21c822b2eafb3e098488a7c12acbb2d708d6b33fca5662ad253c1034d9f34474052263d
|
7
|
+
data.tar.gz: ea9fb77064f3fb6904c8ec56ab0a50fac3f61b23d41dfeeec5d7ee4051442bb869b2c7a53664d0615dbdbe3f2aae6345cea99572b9f8cd4d8de92e16a34f0086
|
data/lib/motion/util.rb
CHANGED
@@ -90,6 +90,124 @@ module RMExtensions
|
|
90
90
|
true
|
91
91
|
end
|
92
92
|
|
93
|
+
# call the block immediately if called on the main thread,
|
94
|
+
# otherwise call it async on the main queue
|
95
|
+
def rmext_inline_or_on_main_q(&block)
|
96
|
+
if NSThread.currentThread.isMainThread
|
97
|
+
block.call
|
98
|
+
else
|
99
|
+
rmext_on_main_q(&block)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# call the block immediately if called on the main thread with the given args,
|
104
|
+
# otherwise call it async on the main queue.
|
105
|
+
# silently ignores nil blocks to avoid if !block.nil? checks, useful for async callbacks
|
106
|
+
# that optionally take a callback
|
107
|
+
def rmext_block_on_main_q(block, *args)
|
108
|
+
unless block.nil?
|
109
|
+
rmext_inline_or_on_main_q do
|
110
|
+
block.call(*args)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
### EXPERIMENTAL
|
116
|
+
|
117
|
+
# takes a unique_id, run_immediately bool, and block
|
118
|
+
# if run_immediately is true, the block is executed immediately and not counted
|
119
|
+
# on the next run loop, the block will be called IF it has been counted at least once.
|
120
|
+
# examples:
|
121
|
+
#
|
122
|
+
# # CALLED will be printed twice. Onces immediately, and once on the next runloop:
|
123
|
+
# 10.times do
|
124
|
+
# rmext_debounce_on_next_runloop(:my_unique_id, true) do
|
125
|
+
# p "CALLED"
|
126
|
+
# end
|
127
|
+
# end
|
128
|
+
#
|
129
|
+
# # CALLED will be printed once, on the next runloop:
|
130
|
+
# 10.times do
|
131
|
+
# rmext_debounce_on_next_runloop(:my_unique_id, false) do
|
132
|
+
# p "CALLED"
|
133
|
+
# end
|
134
|
+
# end
|
135
|
+
#
|
136
|
+
# useful for queuing up something that should happen on the next runloop,
|
137
|
+
# but not every time its called. for example, reloadData. the goal was
|
138
|
+
# to get a similar behavior to how setNeedsDisplay/setNeedsLayout scheduled
|
139
|
+
# display/layout rendering on the next UI runloop pass
|
140
|
+
#
|
141
|
+
def rmext_debounce_on_next_runloop(unique_id, run_immediately, &block)
|
142
|
+
Thread.current["rmext_debounce_on_next_runloop"] ||= {}
|
143
|
+
lookup = Thread.current["rmext_debounce_on_next_runloop"]
|
144
|
+
if lookup.key?(unique_id)
|
145
|
+
lookup[unique_id][0] += 1
|
146
|
+
else
|
147
|
+
lookup[unique_id] = [ 0, lambda do
|
148
|
+
if (debounced_times = lookup[unique_id][0]) > 0
|
149
|
+
# p "we have", debounced_times, "debounced_times queued for unique_id", unique_id
|
150
|
+
block.call
|
151
|
+
else
|
152
|
+
# p "no debounced_times queued for unique_id", unique_id
|
153
|
+
end
|
154
|
+
lookup.delete(unique_id)
|
155
|
+
end ]
|
156
|
+
if run_immediately
|
157
|
+
block.call
|
158
|
+
else
|
159
|
+
lookup[unique_id][0] += 1
|
160
|
+
end
|
161
|
+
# p NSRunLoop.currentRunLoop, NSRunLoop.currentRunLoop.currentMode, lookup[unique_id][1]
|
162
|
+
NSRunLoop.currentRunLoop.performSelector('call', target:lookup[unique_id][1], argument:nil, order:0, modes:[NSRunLoop.currentRunLoop.currentMode])
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def rmext_debounce_selector_on_next_runloop(selector, run_immediately)
|
167
|
+
Thread.current["rmext_debounce_selector_on_next_runloop"] ||= {}
|
168
|
+
lookup = Thread.current["rmext_debounce_selector_on_next_runloop"]
|
169
|
+
if lookup.key?(selector)
|
170
|
+
lookup[selector] += 1
|
171
|
+
else
|
172
|
+
lookup[selector] = 0
|
173
|
+
if run_immediately
|
174
|
+
send(selector)
|
175
|
+
else
|
176
|
+
lookup[selector] += 1
|
177
|
+
end
|
178
|
+
# p NSRunLoop.currentRunLoop, NSRunLoop.currentRunLoop.currentMode, self, selector, lookup[selector]
|
179
|
+
block = lambda do
|
180
|
+
if (debounced_times = lookup[selector]) > 0
|
181
|
+
# p "we have", debounced_times, "debounced_times queued for", self, selector
|
182
|
+
send(selector)
|
183
|
+
else
|
184
|
+
# p "no debounced_times queued for", self, selector
|
185
|
+
end
|
186
|
+
lookup.delete(selector)
|
187
|
+
end
|
188
|
+
NSRunLoop.currentRunLoop.performSelector('call', target:block, argument:nil, order:0, modes:[NSRunLoop.currentRunLoop.currentMode])
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
# more typical debouncing behavior
|
193
|
+
def rmext_debounced(method_name, seconds, *args)
|
194
|
+
new_method_name = "#{method_name}_#{seconds}"
|
195
|
+
unless respond_to?(new_method_name)
|
196
|
+
self.class.send(:define_method, new_method_name) do |*xargs|
|
197
|
+
xargs.unshift(method_name)
|
198
|
+
send(*xargs)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
args.unshift(new_method_name)
|
202
|
+
NSObject.cancelPreviousPerformRequestsWithTarget(self, selector:"rmext_dispatch__send__", object:args)
|
203
|
+
performSelector("rmext_dispatch__send__", withObject:args, afterDelay:seconds)
|
204
|
+
end
|
205
|
+
|
206
|
+
# used internally by `rmext_debounced`
|
207
|
+
def rmext_dispatch__send__(*args)
|
208
|
+
send(*args)
|
209
|
+
end
|
210
|
+
|
93
211
|
end
|
94
212
|
|
95
213
|
end
|