Рекурсивный -flattenMap: с Reactive Cocoa + OctoKit (извлечение графа динамических объектов из веб-службы)

Я пытаюсь предварительно получить граф объектов файлов в репозитории Github, используя Octokit, который зависит от Reactive 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];
            }];
}

В качестве примечания: -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");
 }];

Любая идея, почему он выполняет только верхний уровень? Я бы подумал, что вызов -subscribeNext: на -fetchContentTreeForRepository: будет тем, что выполнит возвращенный сигнал для -flattenMap:, но, кажется, я что-то неправильно понимаю. Это предположение исходит из примера цепочки в файле readme Reactive Cocoa.

изменить: я тупой.


person rnystrom    schedule 01.07.2013    source источник


Ответы (1)


Проблема в том, что вы никогда не инициализируете свои NSMutableArray сигналов:

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

Измените эту первую строку на NSMutableArray *signals = [NSMutableArray new], и она, похоже, сработает.

person mdiep    schedule 01.07.2013
comment
Я мог бы также добавить, что вы можете просто использовать свойство rac_sequence массива directories для выполнения сопоставления каждого каталога с сигналом. Делает то же самое, но немного более декларативно. - person sudo rm -rf; 01.07.2013