Pavel Osipov
Pavel Osipov

Reputation: 2097

How to rebind RACSignal to BOOL variable?

I have a tree-based data structure with Node as its base class:

@interface Node : NSObject
@property (nonatomic, weak) Node *parentNode;
@property (nonatomic, assign) BOOL detached;
@end

When detached variable of parent's node is equal to YES, then the same property of the child should become YES. This behaviour modelled with the following code:

@implementation Node

- (void)setParentNode:(Node *)parentNode {
    _parentNode = parentNode;
    RAC(self, detached) = [RACObserve(_parentNode, detached) filter:^BOOL(id value) {
        return [value boolValue];
    }];
}

@end

How can I rebind detached property when parent is being changed? If do nothing there will be a crash in that case:

Node *node = [Node new];
Node *parentNode = [Node new];
Node *grandparentNode = [Node new];
parentNode.parentNode = grandparentNode;
node.parentNode = parentNode;
[RACObserve(node, detached) subscribeNext:^(id x) {
    NSLog(@"node.detached: %@", x);
}];
Node *newParent = [Node new];
node.parentNode = newParent;
grandparentNode.detached = YES;

I have found the discussion here but I can not realize how to adopt solution their to my case.

Upvotes: 3

Views: 3212

Answers (1)

Justin Spahr-Summers
Justin Spahr-Summers

Reputation: 16973

As a general rule of thumb, avoid constructing signals within setters. It's unnecessarily imperative, and RAC offers many more declarative ways to express what you're trying to do (instead of how to do it).

So, instead of putting anything into -setParentNode:, you can bind to your own property at initialization time (for example):

- (id)init {
    self = [super init];
    if (self == nil) return nil;

    // Use @NO instead if that makes more sense as a default.
    RAC(self, detached, @YES) = [RACObserve(self, parentNode.detached) filter:^(NSNumber *detached) {
        return [detached boolValue];
    }];

    return self;
}

This will update self.detached whenever self.parentNode or self.parentNode.detached changes. If self.parentNode is nil, the property will default to YES.

Upvotes: 9

Related Questions