递归-flattenMap:使用Reactive Cocoa + OctoKit(从Web服务获取动态对象图)

rny*_*rom 5 recursion functional-programming github objective-c reactive-cocoa

我试图在使用Github的库文件的预取的对象图Octokit取决于反应Cococa.我遇到了一个问题,即创建一个信号,递归地向下钻取,直到没有更多的目录被提取为止.这是存储库的示例目录图(注意:文件已被省略以保持图形简单和干净).

RNGridMenu的目录图

- (RACSignal *)fetchContentTreeForRepository:(OCTRepository *)repository {
    return [[self fetchContent:Nil forRepository:repository parentContent:nil] doCompleted:^{
        // fetching tree finished, persist in database
    }];
}

- (RACSignal *)fetchContent:(OCTContent *)content forRepository:(OCTRepository *)repository parentContent:(OCTContent *)parentContent {
    return [[[[self.client fetchContents:content forRepository:repository] collect] deliverOn:RACScheduler.mainThreadScheduler]
            flattenMap:^RACSignal *(NSArray *fetchedContents) {
                // set the contents that were fetched
                id<OCTContentStoreProtocol>store = content ?: repository;
                store.contents = fetchedContents;

                // only search for contents of type "dir" (directory)
                NSArray *directories = [fetchedContents filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"contentType = \"dir\""]];
                NSMutableArray *signals;
                for (OCTContent *fetchedDir in directories) {
                    [signals addObject:[self fetchContent:fetchedDir forRepository:repository parentContent:content]];
                }
                return [RACSignal merge:signals];
            }];
}
Run Code Online (Sandbox Code Playgroud)

作为注释:-fetchContents:forRepository:构建一个请求路径并返回一个RACSignal排队的HTTP请求操作(它尝试遵循OctoKit所做的语义).

我目前遇到的问题是这个设置只执行存储库内容的获取(即图中的顶级对象).-flattenMap:如果调用,则会适当地创建信号数组,并-merge:返回.目的是创建一个递归链,当没有更多目录类型的子目录时结束(应该添加一个-filter:来检查它).

内容是获取Github存储库的整个文件图,并在操作完成时得到通知.这是一个我想如何处理这个问题的例子:

[[[GHDataStore sharedStore] fetchContentTreeForRepository:self.repository]
 subscribeNext:^(NSArray *contents) {
     // this would be called each time a new set of contents is received
     NSLog(@"received %i contents",[contents count]);
 }
 error:^(NSError *error) {
     NSLog(@"error fetching: %@",error.localizedDescription);
 }
 completed:^{
     // this would be called when mapping the graph is finished
     NSLog(@"finished fetching contents");
 }];
Run Code Online (Sandbox Code Playgroud)

知道为什么它只执行顶级?我本来以为叫-subscribeNext:-fetchContentTreeForRepository:会是怎样执行的返回信号-flattenMap:,但似乎我误解的东西.这个假设来自Reactive Cocoa自述文件中的链接示例.

编辑:我很蠢.

mdi*_*iep 4

问题是你永远不会初始化你的NSMutableArray信号:

NSMutableArray *signals;
for (OCTContent *fetchedDir in directories) {
       [signals addObject:[self fetchContent:fetchedDir forRepository:repository parentContent:content]];
}
return [RACSignal merge:signals];
Run Code Online (Sandbox Code Playgroud)

将第一行更改为NSMutableArray *signals = [NSMutableArray new],它似乎有效。

  • 我还可以补充一点,您可以使用“directories”数组的“rac_sequence”属性来执行每个目录到信号的映射。做同样的事情,但更具声明性。 (3认同)