aka*_*lar 0 timer objective-c ios reactive-cocoa
我是ReactiveCocoa的新手,有一个问题我还没找到解决办法.我的应用程序中有一个网络请求,它返回要编码的数据,QR码只有30秒有效.网络请求返回a RACSignal并且我将要在该信号中编码的数据发送到我的视图模型.在视图模型中,我将该数据映射到QR图像,并将其作为视图模型界面中的属性公开.在我创建QR图像后,我想更新一个timeLeftString显示"此代码仅在30秒内有效"的属性,但秒数将随着时间的推移而变化,在完成30秒后,我想再次请求获取另一个有效30秒的QR码数据,之后完成另一个请求,获取数据将有效30秒......直到屏幕被解除.我该如何实现呢?
目前我有这个来获取数据:
- (RACSignal *)newPaymentSignal
{
@weakify(self);
return [[[[APIManager sharedManager] newPayment] map:^id(NSString *paymentToken) {
ZXMultiFormatWriter *writer = [ZXMultiFormatWriter writer];
ZXBitMatrix *result =
[writer encode:paymentToken format:kBarcodeFormatQRCode width:250 height:250 error:nil];
if (!result) {
return nil;
}
CGImageRef cgImage = [[ZXImage imageWithMatrix:result] cgimage];
UIImage *image = [UIImage imageWithCGImage:cgImage];
return UIImagePNGRepresentation(image);
}] doNext:^(NSData *data) {
@strongify(self);
self.qrImageData = data;
}];
}
Run Code Online (Sandbox Code Playgroud)
这对于计时器
- (RACSignal *)timeRemainingSignal
{
@weakify(self);
return [[[RACSignal interval:0.5 onScheduler:[RACScheduler scheduler]] //
startWith:[NSDate date]] //
initially:^{
@strongify(self);
self.expiryDate = [[NSDate date] dateByAddingTimeInterval:30];
}];
}
Run Code Online (Sandbox Code Playgroud)
流程是:从api获取数据,启动计时器,当时间到时,发出新请求以获取新数据并再次启动计时器......并永远重复此操作.
1-从API获取数据后如何启动计时器?
2-如何使此流程永远重复?
3-如何在30秒完成之前停止计时器,如果用户点击用户界面上的按钮,则从头开始流程?
4-我有一个expiryDate属性,在当前日期增加了30秒,因为我认为我将采取差异expiryDate并[NSDate date]决定时间是否到了 - 是否有更好的方法来实现这一点?
5-当屏幕被解除时(或者,当用户点击另一个按钮时),如何在永久重复时取消流量并取消订阅所有内容?
非常感谢您的答案.
我认为拼图的缺失部分是非常有用的flattenMap操作员.它基本上用来自其返回的信号的nexts替换其输入信号中的任何nexts.
这是解决问题的一种方法(我使用发送字符串的简单信号替换了newPaymentSignal方法):
- (RACSignal *)newPaymentSignal
{
return [[RACSignal return:@"token"] delay:2];
}
- (void)start
{
NSInteger refreshInterval = 30;
RACSignal *refreshTokenTimerSignal =
[[RACSignal interval:refreshInterval onScheduler:[RACScheduler mainThreadScheduler]]
startWith:[NSDate date]];
[[[[refreshTokenTimerSignal
flattenMap:^RACStream *(id _)
{
return [self newPaymentSignal];
}]
map:^NSDate *(NSString *paymentToken)
{
// display paymentToken here
NSLog(@"%@", paymentToken);
return [[NSDate date] dateByAddingTimeInterval:refreshInterval];
}]
flattenMap:^RACStream *(NSDate *expiryDate)
{
return [[[[RACSignal interval:1 onScheduler:[RACScheduler mainThreadScheduler]]
startWith:[NSDate date]]
takeUntil:[refreshTokenTimerSignal skip:1]]
map:^NSNumber *(NSDate *now)
{
return @([expiryDate timeIntervalSinceDate:now]);
}];
}]
subscribeNext:^(NSNumber *remaining)
{
// update timer readout here
NSLog(@"%@", remaining);
}];
}
Run Code Online (Sandbox Code Playgroud)
每次外部refreshTokenTimerSignal触发时,它都会映射到一个新的newPaymentSignal,当它返回一个值时,它会被映射到一个有效期,用于创建一个新的"内部"计时器信号,每秒触发一次.
的takeUntil在内侧定时器操作者只要外刷新定时器发送下一完成该信号.
(这里的一个奇怪的事情是,我有一个添加skip:1到refreshTokenTimerSignal,否则内部计时器就不会开始了.我本来期望它没有甚至工作skip:1,也许有人在RAC的内部更好的熟悉可以解释这是为什么.)
为了响应各种事件来打破外部信号的流动,你也可以尝试使用takeUntil和takeUntilBlock使用它.
| 归档时间: |
|
| 查看次数: |
1432 次 |
| 最近记录: |