We had arrays, now let's have sets, too. Refactored out the base redefinition code to make the set case easy to add. --- lib/hotcocoa/kvo_accessors.rb | 39 ++++++++++++++++++++++++++ +------------ 1 files changed, 27 insertions(+), 12 deletions(-) diff --git a/lib/hotcocoa/kvo_accessors.rb b/lib/hotcocoa/ kvo_accessors.rb index 1ecacdb..a029413 100644 --- a/lib/hotcocoa/kvo_accessors.rb +++ b/lib/hotcocoa/kvo_accessors.rb @@ -2,27 +2,42 @@ class Object def self.kvo_array(key, &b) capitalized_key = key.to_s.capitalize - signatures = {:size => { selector: :"countOf#{capitalized_key}", type_signature: "i@:", flip: false }, - :[] => { selector: :"objectIn#{capitalized_key}AtIndex:", type_signature: "@@:i", flip: false }, - :insert => { selector: :"insertObject:in#{capitalized_key}AtIndex:", type_signature: "v@:@i", flip: true }, - :delete_at => { selector: :"removeObjectFrom#{capitalized_key}AtIndex:", type_signature: "v@:i", flip: false } + signatures = { :size => { selector: :"countOf#{capitalized_key}", type_signature: "i@:", flip: false }, + :[] => { selector: :"objectIn#{capitalized_key}AtIndex:", type_signature: "@@:i", flip: false }, + :insert => { selector: :"insertObject:in#{capitalized_key}AtIndex:", type_signature: "v@:@i", flip: true }, + :delete_at => { selector: :"removeObjectFrom#{capitalized_key}AtIndex:", type_signature: "v@:i", flip: false } } + define_methods_with_signatures(signatures, &b) + end + + def self.kvo_set(key, &b) + capitalized_key = key.to_s.capitalize + signatures = { :add => { selector: :"add#{capitalized_key}Object:", type_signature: "v@:@", flip: false }, + :delete => { selector: :"remove#{capitalized_key}Object:", type_signature: "v@:@", flip: false}, + :merge => { selector: :"add#{capitalized_key}:", type_signature: "v@:@", flip: false }, + :subtract => { selector: :"remove#{capitalized_key}:", type_signature: "v@:@", flip: false }, + :set => { selector: :"#{key}", type_signature: "@@:", flip: false } + } + define_methods_with_signatures(signatures, &b) + end + private + def self.define_methods_with_signatures(signatures, &b) c = Module.new c.module_eval &b c.instance_methods.each do |m| signature = signatures[m] if signature - method = c.instance_method(m) - if signature[:flip] - method = Proc.new { |a, b| method.bind(self).call(b, a)} - end - c.send(:define_method, signature[:selector], method) - c.send(:remove_method, m) - c.method_signature(signature[:selector], signature[:type_signature]) + method = c.instance_method(m) + if signature[:flip] + method = Proc.new { |a, b| method.bind(self).call(b, a)} + end + c.send(:define_method, signature[:selector], method) + c.send(:remove_method, m) + c.method_signature(signature[:selector], signature[:type_signature]) elsif not Module.instance_methods.include?(m) - raise ArgumentError, "Method `#{m}' isn't a KVO array accessor" + raise ArgumentError, "Method `#{m}' isn't a KVO array accessor" end end -- 1.6.0.2