7

In my project im trying to work via MVVM, so in VM in .h file

  @property (nonatomic, strong) NSArray    *cities;

in .m file

  - (NSArray *)cities {
        return [[GPCity allObjects] valueForKey:@"name"];
    }

GPCity is a RLMObject subclass How to bind this via ReactiveCocoa (i mean see all cities updates/adds/removes) ?

Something like:

RAC(self, cities) = [[GPCity allObjects] map:(GPCity *)city {return city.name;}];
Zaporozhchenko Oleksandr
  • 4,660
  • 3
  • 26
  • 48
  • Have you had a look at the ReactiveCocoa example in the Realm docs? Maybe you find something there: https://github.com/realm/realm-cocoa/tree/master/examples/ios/objc/RACTableView – joern Jan 16 '16 at 18:17

1 Answers1

2

You can wrap Realm change notifications in a RAC signal:

@interface RLMResults (RACSupport)
- (RACSignal *)gp_signal;
@end

@implementation RLMResults (RACSupport)
- (RACSignal *)gp_signal {
    return [RACSignal createSignal:^(id<RACSubscriber> subscriber) {
        id token = [self.realm addNotificationBlock:^(NSString *notification, RLMRealm *realm) {
            if (notification == RLMRealmDidChangeNotification) {
                [subscriber sendNext:self];
            }
        }];

        return [RACDisposable disposableWithBlock:^{
            [self.realm removeNotification:token];
        }];
    }];
}
@end

and then do:

RAC(self, cities) = [[[RLMObject allObjects] gp_signal]
                     map:^(RLMResults<GPCity *> *cities) { return [cities valueForKey:@"name"]; }];

This will unfortunately update the signal after every write transaction, and not just ones which modify cities. Once Realm 0.98 is released with support for per-RLMResults notifications, you'll be able to do the following, which will only update when a GPCity object is updated:

@interface RLMResults (RACSupport)
- (RACSignal *)gp_signal;
@end

@implementation RLMResults (RACSupport)
- (RACSignal *)gp_signal {
    return [RACSignal createSignal:^(id<RACSubscriber> subscriber) {
        id token = [self addNotificationBlock:^(RLMResults *results, NSError *error) {
            if (error) {
                [subscriber sendError:error];
            }
            else {
                [subscriber sendNext:results];
            }
        }];

        return [RACDisposable disposableWithBlock:^{
            [token stop];
        }];
    }];
}
@end
Thomas Goyne
  • 8,010
  • 32
  • 30
  • Very nice example. Exactly what I was looking for. One suggestion. Before the `addNotificationBlock` line, I'd suggest doing a `[subscriber sendNext:self];` to populate the initial value in the signal. – Sandy Chapman Aug 22 '16 at 17:11