Class: RMExtensions::ObservationProxy
- Inherits:
-
Object
- Object
- RMExtensions::ObservationProxy
- Defined in:
- lib/motion/observation.rb
Overview
# Proxy class used to hold the actual observation and watches for the real # class intended to hold the observation to be deallocated, so the # observation can be cleaned up.
Instance Method Summary collapse
- #add_observer_block(target, key_path, block) ⇒ Object
- #cleanup ⇒ Object
- #dealloc ⇒ Object
-
#initialize(obj) ⇒ ObservationProxy
constructor
A new instance of ObservationProxy.
- #observe(target, keyPath: key_path, options: options, withBlock: block) ⇒ Object
-
#observeValueForKeyPath(key_path, ofObject: target, change: change, context: context) ⇒ Object
NSKeyValueObserving Protocol.
- #off(event, inContext: context, withBlock: block) ⇒ Object
- #off_all ⇒ Object
- #on(event, inContext: context, withBlock: block) ⇒ Object
- #registered?(target, key_path) ⇒ Boolean
- #remove_observer_block(target, key_path) ⇒ Object
- #trigger(event, value) ⇒ Object
- #unobserve(target, keyPath: key_path) ⇒ Object
- #unobserve_all ⇒ Object
Constructor Details
#initialize(obj) ⇒ ObservationProxy
Returns a new instance of ObservationProxy.
87 88 89 90 91 92 93 94 95 |
# File 'lib/motion/observation.rb', line 87 def initialize(obj) @weak_object = WeakRef.new(obj) @desc = obj.inspect @events = NSMapTable.weakToStrongObjectsMapTable @targets = {} if ::RMExtensions.debug? p "created ObservationProxy(#{@desc})" end end |
Instance Method Details
#add_observer_block(target, key_path, block) ⇒ Object
152 153 154 155 156 157 158 |
# File 'lib/motion/observation.rb', line 152 def add_observer_block(target, key_path, block) return if target.nil? || key_path.nil? || block.nil? key_path = key_path.to_s @targets[target] ||= {} @targets[target][key_path] ||= [] @targets[target][key_path].addObject block end |
#cleanup ⇒ Object
106 107 108 109 110 111 112 113 |
# File 'lib/motion/observation.rb', line 106 def cleanup if ::RMExtensions.debug? p "cleanup ObservationProxy(#{@desc})" end unobserve_all off_all true end |
#dealloc ⇒ Object
97 98 99 100 101 102 103 104 |
# File 'lib/motion/observation.rb', line 97 def dealloc @did_dealloc = true cleanup if ::RMExtensions.debug? p "dealloc ObservationProxy(#{@desc})" end super end |
#observe(target, keyPath: key_path, options: options, withBlock: block) ⇒ Object
115 116 117 118 119 |
# File 'lib/motion/observation.rb', line 115 def observe(target, keyPath:key_path, options:, withBlock:block) already_registered = registered?(target, key_path) add_observer_block(target, key_path, block) target.addObserver(self, forKeyPath:key_path, options:, context:nil) unless already_registered end |
#observeValueForKeyPath(key_path, ofObject: target, change: change, context: context) ⇒ Object
NSKeyValueObserving Protocol
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/motion/observation.rb', line 162 def observeValueForKeyPath(key_path, ofObject:target, change:change, context:context) m_desc = nil if ::RMExtensions.debug? m_desc = "~~> ObservationProxy(#{@desc})#observeValueForKeyPath(#{key_path}, ofObject:#{target.inspect.split(" ").first}>, ...)" p "called", m_desc end action = proc do next if @did_dealloc next if target.nil? key_paths = @targets[target] next if key_paths.nil? blocks = key_paths[key_path] next if blocks.nil? blocks = [] + blocks # get a new array that can be popped if ::RMExtensions.debug? p "blocks.size", blocks.size, m_desc end while blk = blocks.pop res = ObservationResponse.new res.context = @weak_object res.value = change[NSKeyValueChangeNewKey] res.old_value = change[NSKeyValueChangeOldKey] res.target = target res.key = key_path res.indexes = change[NSKeyValueChangeIndexesKey] res.kind = change[NSKeyValueChangeKindKey] blk.call(res) end end if NSThread.currentThread.isMainThread if ::RMExtensions.debug? p "inline execution", m_desc end action.call else if ::RMExtensions.debug? p "dispatch execution", m_desc end rmext_on_main_q(&action) end end |
#off(event, inContext: context, withBlock: block) ⇒ Object
219 220 221 222 223 224 225 226 227 |
# File 'lib/motion/observation.rb', line 219 def off(event, inContext:context, withBlock:block) return if event.nil? || block.nil? event = event.to_s context ||= self.class return unless context_events = @events.objectForKey(context) return unless context_event_blocks = context_events.objectForKey(event) context_event_blocks.removeObject block nil end |
#off_all ⇒ Object
229 230 231 |
# File 'lib/motion/observation.rb', line 229 def off_all @events.removeAllObjects end |
#on(event, inContext: context, withBlock: block) ⇒ Object
204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/motion/observation.rb', line 204 def on(event, inContext:context, withBlock:block) return if event.nil? || block.nil? event = event.to_s context ||= self.class unless context_events = @events.objectForKey(context) context_events = {} @events.setObject(context_events, forKey:context) end unless context_event_blocks = context_events.objectForKey(event) context_event_blocks = [] context_events.setObject(context_event_blocks, forKey:event) end context_event_blocks.addObject block end |
#registered?(target, key_path) ⇒ Boolean
148 149 150 |
# File 'lib/motion/observation.rb', line 148 def registered?(target, key_path) !target.nil? && !@targets[target].nil? && @targets[target].has_key?(key_path.to_s) end |
#remove_observer_block(target, key_path) ⇒ Object
127 128 129 130 131 132 133 134 |
# File 'lib/motion/observation.rb', line 127 def remove_observer_block(target, key_path) return if target.nil? || key_path.nil? key_path = key_path.to_s target_hash = @targets[target] if !target_hash.nil? && target_hash.has_key?(key_path) target_hash.delete(key_path) end end |
#trigger(event, value) ⇒ Object
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
# File 'lib/motion/observation.rb', line 233 def trigger(event, value) m_desc = nil if ::RMExtensions.debug? m_desc = "~~> ObservationProxy(#{@desc})#trigger(#{event}, #{value.inspect.split(" ").first }>)" p "called", m_desc end rmext_on_main_q do next if @did_dealloc next if event.nil? event = event.to_s keyEnumerator = @events.keyEnumerator contexts = [] while context = keyEnumerator.nextObject contexts.push context end while context = contexts.pop if context_events = @events.objectForKey(context) if event_blocks = context_events[event] blocks = [] + event_blocks if ::RMExtensions.debug? p "blocks.size", blocks.size, m_desc end while blk = blocks.pop res = EventResponse.new res.context = context res.value = value res.target = @weak_object res.event = event blk.call(res) end end end end end nil end |
#unobserve(target, keyPath: key_path) ⇒ Object
121 122 123 124 125 |
# File 'lib/motion/observation.rb', line 121 def unobserve(target, keyPath:key_path) return unless registered?(target, key_path) target.removeObserver(self, forKeyPath:key_path) remove_observer_block(target, key_path) end |
#unobserve_all ⇒ Object
136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/motion/observation.rb', line 136 def unobserve_all keys = [] + @targets.keys while target = keys.pop target_hash = @targets[target] paths = [] + target_hash.keys while key_path = paths.pop unobserve(target, keyPath:key_path) end end @targets.removeAllObjects end |