rny*_*rom 10 functional-programming github objective-c reactive-cocoa
我正在构建的客户端正在使用Reactive Cocoa和Octokit,到目前为止它已经进展顺利.但是现在我正处于一个我想要获取存储库集合的地步,并且无法绕过这样的"RAC方式".
// fire this when an authenticated client is set
[[RACAbleWithStart([GHDataStore sharedStore], client)
filter:^BOOL (OCTClient *client) {
return client != nil && client.authenticated;
}]
subscribeNext:^(OCTClient *client) {
[[[client fetchUserRepositories] deliverOn:RACScheduler.mainThreadScheduler]
subscribeNext:^(OCTRepository *fetchedRepo) {
NSLog(@" Received new repo: %@",fetchedRepo.name);
}
error:^(NSError *error) {
NSLog(@"Error fetching repos: %@",error.localizedDescription);
}];
} completed:^{
NSLog(@"Completed fetching repos");
}];
Run Code Online (Sandbox Code Playgroud)
我最初假设-subscribeNext:会传递一个NSArray,但现在明白它会返回每个返回的"next"对象的消息,在这种情况下是一个OCTRepository.
现在我可以这样做:
NSMutableArray *repos = [NSMutableArray array];
// most of that code above
subscribeNext:^(OCTRepository *fetchedRepo) {
[repos addObject:fetchedRepo];
}
// the rest of the code above
Run Code Online (Sandbox Code Playgroud)
当然,这是有效的,但它似乎没有遵循RAC启用的功能原则.我真的想在这里坚持惯例.任何关于RAC/Octokit功能的亮点都非常感谢!
mdi*_*iep 14
这在很大程度上取决于您之后要对存储库执行的操作.一旦你拥有了所有的存储库,你似乎想要做一些事情,所以我将建立一个这样做的例子.
// Watch for the client to change
RAC(self.repositories) = [[[[[RACAbleWithStart([GHDataStore sharedStore], client)
// Ignore clients that aren't authenticated
filter:^ BOOL (OCTClient *client) {
return client != nil && client.authenticated;
}]
// For each client, execute the block. Returns a signal that sends a signal
// to fetch the user repositories whenever a new client comes in. A signal of
// of signals is often used to do some work in response to some other work.
// Often times, you'd want to use `-flattenMap:`, but we're using `-map:` with
// `-switchToLatest` so the resultant signal will only send repositories for
// the most recent client.
map:^(OCTClient *client) {
// -collect will send a single value--an NSArray with all of the values
// that were send on the original signal.
return [[client fetchUserRepositories] collect];
}]
// Switch to the latest signal that was returned from the map block.
switchToLatest]
// Execute a block when an error occurs, but don't alter the values sent on
// the original signal.
doError:^(NSError *error) {
NSLog(@"Error fetching repos: %@",error.localizedDescription);
}]
deliverOn:RACScheduler.mainThreadScheduler];
Run Code Online (Sandbox Code Playgroud)
self.repositories每当从客户端更新存储库时,现在将更改(并触发KVO通知).
有几点需要注意:
subscribeNext:尽可能避免.使用它的功能模式以外的步骤(如做doNext:和doError:,但他们也是有帮助的工具,在次).一般来说,您想要考虑如何将信号转换为满足您需求的信号.
如果要将一个或多个工作链接在一起,通常需要使用flattenMap:.更一般地说,您想要开始考虑信号信号 - 发送代表其他工作的其他信号的信号.
您经常希望等待尽可能长时间将工作移回主线程.
在思考问题时,有时候有必要先写出每个信号来考虑a)你拥有什么,b)你想要什么,以及c)如何从一个到另一个.
编辑:更新以解决@JustinSpahrSummers的评论如下.