I don't want anyone to think that I am not a big fan of ReactiveCocoa. I'm a HUGE FAN of it!
But look how LONG it took for something like this to come about. Cocoa is an OLD OLD system, and even though KVO/KVC wasn't there at the birth, it has been there at least a decade. I pretty much gave up on Obj-C in favor of RubyMotion, and look at our landscape: Futuristic, ProMotion, Formotion, Geomotion, Elevate, Teacup - all of these projects bring expressiveness to Cocoa, and RubyMotion is barely a year old.
So what I meant to say is that Obj-C suffers from a lack of expressiveness - this has nothing to do with ReactiveCocoa, that's just my example. To illustrate my point, I will translate the first example of the ReactiveCocoa README. I encourage you to read the ReactiveCocoa source and try and consolidate all the code that is used to handle this function. I will include all of the Ruby code that is necessary for my translation to work.
I do have one qualm with ReactiveCocoa: the names. I'm going to translate the comments into (what I hope is equivalent) plain English.
// When self.username changes, log the new name to the console.
//
// RACAble(self.username) creates a new RACSignal that sends a new value
// whenever the username changes. -subscribeNext: will execute the block
// whenever the signal sends a value.
[RACAble(self.username) subscribeNext:^(NSString *newName) {
NSLog(@"%@", newName);
}];
# When self.username changes, log the new name to the console
#
# self.kvc(:username) creates an object you can use to observe the value of `self.username`
self.kvc(:username).observe do |new_name|
puts new_name
end
# here's the code to add that feature:
# add the `kvc` method to all objects
class Object
def kvc(property)
KVC.new(self, property)
end
end
# add observing to Procs
class Proc
def observeValueForKeyPath(path, ofObject: target, change: change, context: ctx)
self.call(change['new'])
end
end
class KVC
attr :target
attr :key_path
def initialize(target, key_path)
@target = target
@key_path = key_path.to_s
end
def observe(&block)
self.target.addObserver(block, forKeyPath: self.key_path.to_s, options: NSKeyValueObservingOptionNew, context: nil)
end
end