Search code examples
iosobjective-cxcodereactive-cocoa

Dynamically select property to observe with RAC


I have a lot of UISegmentedControls (74 actually) in one view that I want to two-way bind with their respective model properties using RACChannel. To reduce the code, I want to assign these bindings at runtime using enumeration of an IBOutletCollection.

In order to make this work, I have to come up with a way to select the correct property dynamically. I have 74 properties on my model that follows this naming convention: "item1a, item1b, item1c, item2a...".

On every UISegmentedControl I have an attribute, "name", that I can extract at runtime to know which control should be bound to which property.

What I would like to do is essentially

RACCHannelTerminal *modelTerminal = RACChannelTo(self, "DYNAMIC PROPERTY NAME");

I can get the value for a dynamic property name by

[self valueForKey:@"item1a"];

but this doesn't give the the actual property to observe, just a value.

Is there any way of doing what is described?


Solution

  • As from documenation - RACChanelTo - is just a macro, which you can rewrite as

    [[RACKVOChannel alloc] initWithTarget:<#(NSObject *)#> keyPath:<#(NSString *)#> nilValue:<#(id)#>]
    

    So, instead of using RACChanelTo(,) use

    RACCHannelTerminal *modelTerminal = [[RACKVOChannel alloc] initWithTarget:self keyPath:@"DYNAMIC PROPERTY NAME" nilValue:nil];
    

    WARNING

    From Reactive Cocoa header

    /// Do not use this directly. Use the RACChannelTo macro above.

    define RACChannelTo_(TARGET, KEYPATH, NILVALUE) \

    [[RACKVOChannel alloc] initWithTarget:(TARGET) keyPath:@keypath(TARGET, KEYPATH)
    

    nilValue:(NILVALUE)][@keypath(RACKVOChannel.new, followingTerminal)]

    Hope this helps you