如何根据另一个信号发出ReactiveCocoa信号?

时间:2015-01-16 17:33:43

标签: reactive-cocoa

我想基于另一个信号发射来发射信号。这与combineLatest真的不一样:reduce,因为'trigger'信号不能轻易KVO(它是一个字典,我需要观察值的变化)。

这是我想解决的问题,我有兴趣听听解决方案:

我有一个需要在表格视图中显示的分层数据列表。此外,可以使用搜索字符串过滤此数据。所以,我需要能够搜索,然后折叠/扩展数据。所以,我有:

// simple object that can have nested children
@interface ExpandableNode : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSMutableArray *children;
@end

// NOTE: The code below is highly simplified - no strongify/weakify, not making
// return objects immutable, etc. This should be seen more like pseudo-code as opposed to
// working production code.

// I'm assigning them directly here, but assume this comes from remote source
// eg. webservice.
self.results = @[@"Copenhagen", @"New York", @"Kuala Lumpur"];
self.childrenMap = @{@"New York" : @[@"Queens", @"Brooklyn"]};

// this dictionary keeps the expanded state, so when expanded, it looks like
// > Copenhagen
// ˅ New York
//     Queens
//     Brooklyn
// > Kuala Lumpur
//
self.isExpanded = [NSMutableDictionary dictionary];

// this chunk of code returns an array of *unexpanded* nodes...
RACSignal *items = [RACSignal combineLatest:@[RACObserve(self, results), RACObserve(self, childrenMap)]
                                     reduce:^id(NSArray *results, NSDictionary *childrenMap) {
                                         NSMutableArray *items = [NSMutableArray array];
                                         for (NSString *item in results) {
                                             ExpandableNode *node = [[ExpandableNode alloc] init];
                                             node.name = item;
                                             if (childrenMap[item]) {
                                                 for (NSString *child in childrenMap[item]) {
                                                     ExpandableNode *childNode = [[ExpandableNode alloc] init];
                                                     childNode.name = child;
                                                     [node.children addObject:childNode];
                                                 }
                                             }
                                             [items addObject:node];
                                         }
                                         return items;
                                     }];
// ...and this code expands them out
RACSignal *flattenedItems = [items map:^id(NSArray *items) {
    NSMutableArray *flattenedItems = [NSMutableArray array];
    for (ExpandableNode *node in items) {
        [flattenedItems addObject:node];
        if ([self.isExpanded[node.name] boolValue]) {
            [flattenedItems addObjectsFromArray:node.children];
        }
    }
    return flattenedItems;
}];

// when flattenedItems update, I reload my table view(handwaving alot here)
[flattenedItems subscribeNext:^(id x) {
    [self.tableView reloadData];
}];

现在,如果我需要展开或折叠项目,我会修改'isExpanded'字典。理想情况下,只有第二个信号块触发,因为我原来的未扩展节点没有改变。我只想'重新加载'flattenedItems。

我想要的是一种信号让另一个信号“重复”的方法。但我不确定如何最好地解决这个问题。

0 个答案:

没有答案
相关问题