Ios 检测RAC信号的最佳实践

Ios 检测RAC信号的最佳实践,ios,objective-c,reactive-programming,reactive-cocoa,Ios,Objective C,Reactive Programming,Reactive Cocoa,我的任务是向应用程序添加一些插装逻辑,以跟踪各种API调用的延迟。我正在努力找到一种干净、无副作用的方法,向返回RACSignal(延迟执行API调用)的方法添加计时工具 考虑 使用ReactiveCocoa@1.9.5(目前无法升级) 使用@0.0.2 我更喜欢在ViewModel层设置计时,而不是修改Parse RACExtensions。这是因为VM有我想要记录的额外信息,比如查询参数,并且我不需要检测每个API调用 仅在收到已完成的事件时记录计时 本着无痛器械的精神,呼叫者的负担应该尽

我的任务是向应用程序添加一些插装逻辑,以跟踪各种API调用的延迟。我正在努力找到一种干净、无副作用的方法,向返回RACSignal(延迟执行API调用)的方法添加计时工具

考虑
  • 使用ReactiveCocoa@1.9.5(目前无法升级)
  • 使用@0.0.2
  • 我更喜欢在ViewModel层设置计时,而不是修改Parse RACExtensions。这是因为VM有我想要记录的额外信息,比如查询参数,并且我不需要检测每个API调用
  • 仅在收到
    已完成的事件时记录计时
  • 本着无痛器械的精神,呼叫者的负担应该尽可能小
尝试解决方案 我唯一能想到的就是创建一个具体的RACSubscriber子类来处理计时器逻辑。除了讨厌的子类之外,这显然并不理想,因为它需要显式的
subscribe:
,这反过来又需要对源信号进行
replay
。此外,调用者还有一个负担,因为他们必须至少重构以获得信号的临时句柄

@interface SignalTimer : RACSubscriber

@property (nonatomic) NSDate *startDate;

@end

@implementation SignalTimer

- (void)didSubscribeWithDisposable:(RACDisposable *)disposable
{
    [super didSubscribeWithDisposable:disposable];

    self.startDate = [NSDate date];
}

- (void)sendCompleted
{
    NSTimeInterval duration = [[NSDate date] timeIntervalSinceDate:self.startDate];
    NSLog(@"Time elapsed: %f", duration);

    [super sendCompleted];
}

@end
用法如下所示:

- (RACSignal*)saveFoo:(Foo*)fooParseObj {
    RACSignal *save = [[fooParseObj rac_save] replay]; // Don't forget replay!
    [save subscribe:[[SignalTimer alloc] initWithName@"Saving the user's foo object"]];
    return save;
}
显然,我对这个实现不满意

最后的想法 理想情况下,我想要这样一个链式方法,但我不确定如何实现它/如果能够在分类方法中处理冷信号而不产生不良副作用(比如在接收器上调用
replay


想法?

所以我想我让这条路变得比需要的更难了。下面的分类解决方案似乎更为惯用,但我希望得到任何反馈

@interface RACSignal (Timing)

- (instancetype)logTimingWithName:(NSString*)name;

@end

@implementation RACSignal (Timing)

- (instancetype)logTimingWithName:(NSString*)name
{
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

        NSDate* startDate = [NSDate date];

        return [self subscribeNext:^(id x) {
            [subscriber sendNext:x];
        } error:^(NSError *error) {
            [subscriber sendError:error];
        } completed:^{
            NSTimeInterval duration = [[NSDate date] timeIntervalSinceDate:startDate];
            NSLog(@"%@: %f sec", name, duration);

            [subscriber sendCompleted];
        }];
    }];
}

@end
@接口信号(定时)
-(instancetype)logTimingWithName:(NSString*)名称;
@结束
@执行信号(定时)
-(instancetype)logTimingWithName:(NSString*)名称
{
返回[RACSignal createSignal:^RACSignal*(id订户){
NSDate*开始日期=[NSDate日期];
return[self-subscribeNext:^(id x){
[用户发送下一步:x];
}错误:^(N错误*错误){
[订户发送错误:错误];
}已完成:^{
NSTimeInterval持续时间=[[NSDate date]timeIntervalSinceDate:startDate];
NSLog(@“%@:%f秒”,名称,持续时间);
[用户发送完成];
}];
}];
}
@结束

我觉得不错!虽然您不需要新的
NSDate
来计算增量,但只需使用
startDate.timeintervalncesnow
并将其取反即可。
@interface RACSignal (Timing)

- (instancetype)logTimingWithName:(NSString*)name;

@end

@implementation RACSignal (Timing)

- (instancetype)logTimingWithName:(NSString*)name
{
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

        NSDate* startDate = [NSDate date];

        return [self subscribeNext:^(id x) {
            [subscriber sendNext:x];
        } error:^(NSError *error) {
            [subscriber sendError:error];
        } completed:^{
            NSTimeInterval duration = [[NSDate date] timeIntervalSinceDate:startDate];
            NSLog(@"%@: %f sec", name, duration);

            [subscriber sendCompleted];
        }];
    }];
}

@end