5

Reactive Cococaに依存するOctokitを使用して、Githubリポジトリ内のファイルのオブジェクトグラフをプリフェッチしようとしています。私は、フェッチするディレクトリがなくなるまで、再帰的にドリルダウンするシグナルを生成する問題に取り掛かります。ここには、repository of mineのディレクトリグラフの例があります(注:ファイルは、グラフをシンプルできれいにするために省略されています)。注意点として再帰的な-flattenMap:Reactive Cocoa + OctoKit(Webサービスから動的オブジェクトグラフを取得)

Directory graph of 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]; 
      }]; 
} 

-fetchContents:forRepository:は、要求パスを構築し、HTTP要求操作を(それは意味論OctoKit doesに追従しようとする)エンキューRACSignalを返します。

私が現在実行している問題は、このセットアップではリポジトリの内容(つまり、グラフの最上位オブジェクト)の取得のみが実行されることです。 -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"); 
}]; 

トップレベルのみを実行する理由は何ですか?私はを-fetchContentTreeForRepository:に呼び出すと-flattenMap:の返信信号を実行するとは思っていたが、何かを誤解しているようだ。この前提は、Reactive Cocoaのreadmeのchaining exampleにあります。

編集:NSMutableArray *signals = [NSMutableArray new]への最初の行

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

変更と動作するようです:I am dumb.

答えて

4

問題は、信号のあなたのNSMutableArrayを初期化しないことです。

+3

......... dammit – rnystrom

+3

'ディレクトリ'配列の 'rac_sequence'プロパティを使って、各ディレクトリのマップをシグナルに渡すこともできます。同じことをしますが、もう少し宣言的です。 –