Class: RMExtensions::ObservationProxy

Inherits:
Object
  • Object
show all
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.

Constant Summary collapse

COLLECTION_OPERATIONS =
[ NSKeyValueChangeInsertion, NSKeyValueChangeRemoval, NSKeyValueChangeReplacement ]
DEFAULT_OPTIONS =
NSKeyValueObservingOptionNew

Instance Method Summary collapse

Constructor Details

#initialize(desc) ⇒ ObservationProxy

Returns a new instance of ObservationProxy.



78
79
80
81
82
83
# File 'lib/motion/observation.rb', line 78

def initialize(desc)
  @desc = desc
  @events = {}
  @targets = {}
  # p "created #{self.inspect} for #{@desc}"
end

Instance Method Details

#add_observer_block(target, key_path, &block) ⇒ Object



131
132
133
134
135
136
# File 'lib/motion/observation.rb', line 131

def add_observer_block(target, key_path, &block)
  return if target.nil? || key_path.nil? || block.nil?
  @targets[target] ||= {}
  @targets[target][key_path.to_s] ||= []
  @targets[target][key_path.to_s] << block
end

#collection?(change) ⇒ Boolean

Returns:

  • (Boolean)


151
152
153
# File 'lib/motion/observation.rb', line 151

def collection?(change)
  COLLECTION_OPERATIONS.include?(change[NSKeyValueChangeKindKey])
end

#deallocObject

clean up on dellocation



86
87
88
89
90
91
# File 'lib/motion/observation.rb', line 86

def dealloc
  # p "dealloc #{self.inspect} for #{@desc}"
  unobserve_all
  off_all
  super
end

#observe(target, key_path, &block) ⇒ Object



93
94
95
96
# File 'lib/motion/observation.rb', line 93

def observe(target, key_path, &block)
  target.addObserver(self, forKeyPath:key_path, options:DEFAULT_OPTIONS, context:nil) unless registered?(target, key_path)
  add_observer_block(target, key_path, &block)
end

#observeValueForKeyPath(key_path, ofObject: target, change: change, context: context) ⇒ Object

NSKeyValueObserving Protocol



140
141
142
143
144
145
146
147
148
149
# File 'lib/motion/observation.rb', line 140

def observeValueForKeyPath(key_path, ofObject:target, change:change, context:context)
  return if target.nil?
  key_paths = @targets[target] || {}
  blocks = key_paths[key_path] || []
  blocks.each do |block|
    args = [ change[NSKeyValueChangeNewKey] ]
    args << change[NSKeyValueChangeIndexesKey] if collection?(change)
    block.call(*args)
  end
end

#off(event, &block) ⇒ Object



161
162
163
164
165
# File 'lib/motion/observation.rb', line 161

def off(event, &block)
  return if event.nil? || block.nil? || !@events.key?(event.to_s)
  @events[event.to_s].delete_if { |b| b == block }
  nil
end

#off_allObject



167
168
169
# File 'lib/motion/observation.rb', line 167

def off_all
  @events.clear
end

#on(event, &block) ⇒ Object



155
156
157
158
159
# File 'lib/motion/observation.rb', line 155

def on(event, &block)
  return if event.nil? || block.nil?
  @events[event.to_s] ||= []
  @events[event.to_s] << block
end

#registered?(target, key_path) ⇒ Boolean

Returns:

  • (Boolean)


127
128
129
# File 'lib/motion/observation.rb', line 127

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



104
105
106
107
108
109
110
111
# File 'lib/motion/observation.rb', line 104

def remove_observer_block(target, key_path)
  return if target.nil? || key_path.nil?

  key_paths = @targets[target]
  if !key_paths.nil? && key_paths.has_key?(key_path.to_s)
    key_paths.delete(key_path.to_s)
  end
end

#trigger(event, *args) ⇒ Object



171
172
173
174
175
176
177
# File 'lib/motion/observation.rb', line 171

def trigger(event, *args)
  return if event.nil? || !@events.key?(event.to_s)
  @events[event.to_s].each do |block|
    block.call(*args)
  end
  nil
end

#unobserve(target, key_path) ⇒ Object



98
99
100
101
102
# File 'lib/motion/observation.rb', line 98

def unobserve(target, key_path)
  return unless registered?(target, key_path)
  target.removeObserver(self, forKeyPath:key_path)
  remove_observer_block(target, key_path)
end

#unobserve_allObject



113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/motion/observation.rb', line 113

def unobserve_all
  keys = @targets.keys.clone
  while keys.size > 0
    target = keys.pop
    target_hash = @targets[target]
    paths = target_hash.keys.clone
    while paths.size > 0
      key_path = paths.pop
      target.removeObserver(self, forKeyPath:key_path)
    end
  end
  @targets.clear
end