[MacRuby-devel] Key Value Observing module

Matt Massicotte massicotte at apple.com
Mon Nov 29 08:36:09 PST 2010


I'm not familiar with the Ruby observer mechanism you refer to - could you post a link?

Matt

On Nov 29, 2010, at 6:34 AM, Alan Skipp wrote:

> I hope people don't mind me posting this bit of code to the list, but I hope it will be of some use to others and would also be interested to hear if the technique has any problems which I've not foreseen.
> 
> Ruby has its own means of implementing the observer pattern, but as Key Value Observing (KVO) is so pervasive in cocoa, it would be good if it was easy to use. The module is an attempt at making KVO a bit more pleasant to use in macruby. 
> The ideas have been adapted/stolen from here:
> 
> https://gist.github.com/153676
> 
> The following is an example of how to have a block of code executed asynchronously every time a property of an instance variable changes
> 
> self.add_observer_for_key_path('person.first_name', async:true) do |object,change|
>     object.do_expensive_calculation #will not block main thread
> end
> 
> A concern I do have is that the object which wants to receive KVO notifications holds an array of Observer objects. These Observer objects hold a reference to the object receiving the KVO notifications. Is this going to cause havoc with garbage collection?
>  
> module KVO
> 
>   class Observer
>     require 'dispatch'
> 
>     attr_reader :observee, :path
>     def initialize(object, path, async, block, opts=0)
>       @observee = object
>       @path = path
>       @async = async
>       @block = block		  
>       @observee.addObserver(self, forKeyPath:path, options:opts, context:nil)
>     end
> 
>     def observeValueForKeyPath(path, ofObject:object, change:change, context:context)
>       if @async
>         Dispatch::Job.new { @block.call(object, change) } 
>       else
>         @block.call(object, change) 
>       end
>     end
> 
>     def cancel_observation
>       @observee.removeObserver(self, forKeyPath:@path)
>     end
>   end
> 
>   def add_observer_for_key_path(path, async:async, &block)
>     (@_observers_array_ ||= []) << Observer.new(self, path, async, block)
>   end
> 
>   def add_observer_for_key_path(path, async:async, options:opts, &block)
>     (@_observers_array_ ||= []) << Observer.new(self, path, async, block, opts)
>   end
> 
>   def remove_observer_for_key_path(path)
>     observer = @_observers_array_.find {|o| o.path == path && o.observee == self} if @_observers_array_
>     @_observers_array_.delete(observer) and observer.cancel_observation if observer
>   end
>   
> end
> _______________________________________________
> MacRuby-devel mailing list
> MacRuby-devel at lists.macosforge.org
> http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-devel/attachments/20101129/d67ab510/attachment.html>


More information about the MacRuby-devel mailing list