gpt4 book ai didi

ios - ReactiveCocoa 中的自动重复倒数计时器

转载 作者:行者123 更新时间:2023-11-28 18:31:02 25 4
gpt4 key购买 nike

我是 ReactiveCocoa 的新手,有一个问题我还没有找到解决的方法。我的应用程序中有一个网络请求,它返回要编码为二维码的数据,该二维码的有效期仅为 30 秒。网络请求返回一个 RACSignal,我将要在该信号中编码的数据发送到我的 View 模型。在 View 模型中,我将该数据映射到 QR 图像,并将其作为属性公开在我的 View 模型界面中。创建 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;
}];
}

这个是定时器

- (RACSignal *)timeRemainingSignal
{
@weakify(self);
return [[[RACSignal interval:0.5 onScheduler:[RACScheduler scheduler]] //
startWith:[NSDate date]] //
initially:^{
@strongify(self);
self.expiryDate = [[NSDate date] dateByAddingTimeInterval:30];
}];
}

流程是:从 api 获取数据,启动计时器,当时间到了时发出新请求以获取新数据并再次启动计时器......并永远重复此过程。

1- 从 API 获取数据后如何启动计时器?

2- 我如何让这个流程永远重复?

3- 如果用户点击用户界面上的按钮,如何在 30 秒完成之前停止计时器并从头开始流程?

4- 我有一个 expiryDate 属性,它被添加到当前日期 30 秒,因为我想我会取 expiryDate[NSDate date] 的区别 来决定时间是否到了 - 有没有更好的方法来实现这个?

5- 当它永远重复时如何中断流程并在屏幕关闭时(或者说,当用户点击另一个按钮时)取消订阅所有内容?

非常感谢您的回答。

最佳答案

我认为缺少的一 block 拼图是非常有用的 flattenMap 运算符。它实质上是用它返回的信号中的下一个替换其传入信号中的任何下一个。

这是解决您的问题的一种方法(我用发送字符串的简单信号替换了您的 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);
}];
}

每次外部 refreshTokenTimerSignal 触发时,它都会映射到一个新的 newPaymentSignal,而当它返回一个值时,它又映射到一个到期日期,该日期被使用创建一个每秒触发的新“内部”定时器信号。

一旦外部刷新计时器发送下一个信号,内部计时器上的 takeUntil 运算符就会完成该信号。

(这里有一个奇怪的事情是我必须向 refreshTokenTimerSignal 添加一个 skip:1,否则内部定时器永远不会启动。我本以为它会即使没有 skip:1 也能正常工作,也许更精通 RAC 内部结构的人可以解释这是为什么。)

要中断响应各种事件的外部信号流,您也可以尝试使用 takeUntiltakeUntilBlock

关于ios - ReactiveCocoa 中的自动重复倒数计时器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30245302/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com