Class: RMExtensions::EventsProxy

Inherits:
Object
  • Object
show all
Defined in:
lib/motion/events.rb

Overview

Proxy class used to hold the actual listeners and contexts where listening and watches for the real class intended to hold the observation to be deallocated, so the events can be cleaned up.

Instance Method Summary collapse

Constructor Details

#initialize(obj) ⇒ EventsProxy

Returns a new instance of EventsProxy.



69
70
71
72
73
74
75
76
77
# File 'lib/motion/events.rb', line 69

def initialize(obj)
  @weak_object = WeakRef.new(obj)
  @desc = obj.inspect
  @events = NSMapTable.weakToStrongObjectsMapTable
  @listenings = NSHashTable.weakObjectsHashTable
  if ::RMExtensions.debug?
    p "created EventsProxy(#{@desc})"
  end
end

Instance Method Details

#cleanupObject



88
89
90
91
92
# File 'lib/motion/events.rb', line 88

def cleanup
  off_all
  off_all_context
  true
end

#deallocObject



79
80
81
82
83
84
85
86
# File 'lib/motion/events.rb', line 79

def dealloc
  @did_dealloc = true
  cleanup
  if ::RMExtensions.debug?
    p "dealloc EventsProxy(#{@desc})"
  end
  super
end

#listening_to(object) ⇒ Object



112
113
114
115
116
117
# File 'lib/motion/events.rb', line 112

def listening_to(object)
  if ::RMExtensions.debug?
    p "listening_to object", object.class, "from context", @weak_object.class
  end
  @listenings.addObject(object)
end

#now_and_on(event, inContext: context, withBlock: block) ⇒ Object



119
120
121
122
123
124
125
126
127
128
129
# File 'lib/motion/events.rb', line 119

def now_and_on(event, inContext:context, withBlock:block)
  rmext_inline_or_on_main_q do
    res = EventResponse.new
    res.context = context
    res.value = nil
    res.target = @weak_object
    res.event = event
    block.call(res)
  end
  on(event, inContext:context, withBlock:block)
end

#off(event, inContext: context, withBlock: block) ⇒ Object



131
132
133
134
135
136
137
138
139
# File 'lib/motion/events.rb', line 131

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_allObject



150
151
152
# File 'lib/motion/events.rb', line 150

def off_all
  @events.removeAllObjects
end

#off_all_contextObject



158
159
160
161
162
163
164
165
166
# File 'lib/motion/events.rb', line 158

def off_all_context
  while object = @listenings.anyObject
    if ::RMExtensions.debug?
      p "remove object", object.class, "from context", @weak_object.class
    end
    @listenings.removeObject(object)
    object.rmext_events_proxy.off_context(@weak_object)
  end
end

#off_context(context) ⇒ Object



154
155
156
# File 'lib/motion/events.rb', line 154

def off_context(context)
  @events.setObject(nil, forKey:context)
end

#on(event, inContext: context, withBlock: block) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/motion/events.rb', line 94

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
  block.weak!
  context_event_blocks.addObject block
  # i.e.: controller/view listening_to model
  context.rmext_events_proxy.listening_to(@weak_object)
end

#once(event, inContext: context, withBlock: block) ⇒ Object



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

def once(event, inContext:context, withBlock:block)
  block.weak!
  once_block = lambda do |opts|
    off(event, inContext:context, withBlock:once_block)
    block.call(opts)
  end
  on(event, inContext:context, withBlock:once_block)
end

#trigger(event, value) ⇒ Object



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
203
# File 'lib/motion/events.rb', line 168

def trigger(event, value)
  # m_desc = nil
  # if ::RMExtensions.debug?
  #   m_desc = "~~> EventsProxy(#{@desc})#trigger(#{event}, #{value.inspect.split(" ").first }>)"
  #   p "called", m_desc
  # end
  rmext_inline_or_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