Mat*_*man 10 objective-c reactive-programming ios reactive-cocoa
我正在研究一些通过websockets与远程API交互的代码.我的数据层负责建立和监控websocket连接.它还包含应用程序可用于排队要发送的websocket消息的方法.应用程序代码不应该负责检查websocket连接的状态,即"即发即忘".
理想情况下,我希望数据层的功能如下:
self.isConnected == NO)的连接时,消息在内部缓冲.self.isConnected == YES)时,立即发送缓冲的消息,并立即发送任何后续消息.这是我能够提出的:
#import "RACSignal+Buffering.h"
@implementation RACSignal (Buffering)
- (RACSignal*)bufferWithSignal:(RACSignal*)shouldBuffer
{
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];
NSMutableArray* bufferedValues = [[NSMutableArray alloc] init];
__block BOOL buffering = NO;
void (^bufferHandler)() = ^{
if (!buffering)
{
for (id val in bufferedValues)
{
[subscriber sendNext:val];
}
[bufferedValues removeAllObjects];
}
};
RACDisposable* bufferDisposable = [shouldBuffer subscribeNext:^(NSNumber* shouldBuffer) {
buffering = shouldBuffer.boolValue;
bufferHandler();
}];
if (bufferDisposable)
{
[disposable addDisposable:bufferDisposable];
}
RACDisposable* valueDisposable = [self subscribeNext:^(id x) {
[bufferedValues addObject:x];
bufferHandler();
} error:^(NSError *error) {
[subscriber sendError:error];
} completed:^{
[subscriber sendCompleted];
}];
if (valueDisposable)
{
[disposable addDisposable:valueDisposable];
}
return disposable;
}];
}
@end
Run Code Online (Sandbox Code Playgroud)
最后,这是如何使用它的伪代码:
@interface APIManager ()
@property (nonatomic) RACSubject* requests;
@end
@implementation WebsocketDataLayer
- (id)init
{
self = [super init];
if (self) {
RACSignal* connectedSignal = RACObserve(self, connected);
self.requests = [[RACSubject alloc] init];
RACSignal* bufferedApiRequests = [self.requests bufferWithSignal:connectedSignal];
[self rac_liftSelector:@selector(sendRequest:) withSignalsFromArray:@[bufferedApiRequests]];
}
return self;
}
- (void)enqueueRequest:(NSString*)request
{
[self.requests sendNext:request];
}
- (void)sendRequest:(NSString*)request
{
DebugLog(@"Making websocket request: %@", request);
}
@end
Run Code Online (Sandbox Code Playgroud)
我的问题是:这是缓冲价值的正确方法吗?是否有更惯用的RAC处理方式?
Jus*_*ers 11
缓冲可以被认为是适用于单个请求的东西,这导致使用-flattenMap:和自然实现RACObserve:
@weakify(self);
RACSignal *bufferedRequests = [self.requests flattenMap:^(NSString *request) {
@strongify(self);
// Waits for self.connected to be YES, or checks that it already is,
// then forwards the request.
return [[[[RACObserve(self, connected)
ignore:@NO]
take:1]
// Replace the property value with our request.
mapReplace:request];
}];
Run Code Online (Sandbox Code Playgroud)
如果订购很重要,您可以-flattenMap:使用-map:plus 替换-concat.这些实现避免了对任何自定义操作符的需要,并且无需手动订阅(这是众所周知的混乱).
| 归档时间: |
|
| 查看次数: |
1673 次 |
| 最近记录: |