如何将RACSignal重新绑定到BOOL变量?

Pav*_*pov 3 objective-c reactive-cocoa

我有一个基于树的数据结构,Node作为基类:

@interface Node : NSObject
@property (nonatomic, weak) Node *parentNode;
@property (nonatomic, assign) BOOL detached;
@end
Run Code Online (Sandbox Code Playgroud)

当父节点的分离变量等于YES时,子节点的相同属性应该变为YES.此行为使用以下代码建模:

@implementation Node

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

@end
Run Code Online (Sandbox Code Playgroud)

如何在更改父级时重新绑定已分离的属性?如果什么都不做,那么在这种情况下会发生崩溃:

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;
Run Code Online (Sandbox Code Playgroud)

我在这里找到了讨论但是我无法意识到如何在我的案例中采用解决方案.

Jus*_*ers 9

作为一般经验法则,避免在setter中构造信号.这是不必要的势在必行,而RAC提供了许多更具声明的方式来表达什么,你现在要做的(而不是如何做到这一点).

因此,-setParentNode:您可以在初始化时(例如)绑定到您自己的属性,而不是放入任何东西:

- (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;
}
Run Code Online (Sandbox Code Playgroud)

这将更新self.detachedself.parentNodeself.parentNode.detached变化.如果self.parentNodenil,则该属性将默认为YES.