I'm finding myself using the following little class quite a bit to present a changing set of signals as one merged signal. Is there a more elegant way to accomplish the same thing?
@interface SignalSet : NSObject
@property (nonatomic, readonly) RACSignal *mergedSignal;
- (void)addSignal:(RACSignal *)signal;
@end
@implementation SignalSet
- (instancetype)init {
self = [super init];
if (self) {
_signals = [NSSet new];
_mergedSignal = [[RACObserve(self, signals) map:^RACSignal *(NSSet *signals) {
return [RACSignal merge:signals];
}] switchToLatest];
}
return self;
}
- (void)addSignal:(RACSignal *)signal {
self.signals = [self.signals setByAddingObject:signal];
[signal finally:^{
// Remove the signal from the set to release it
self.signals = [[NSSet alloc] initWithArray:[[self.signals rac_sequence] ignore:signal].array];
}];
}
@end
Sure, you can accomplish roughly the same interface with a RACSubject
:
RACSubject *signalSet = [RACSubject subject];
RACSignal *mergedSignals = [signalSet flatten:0];
// Add a signal
[signalSet sendNext:someSignal];
Better yet, depending on your requirements, you may be able to avoid RACSubject
:
RACSignal *mergedSignals = [RACSignal never];
// Add a signal
mergedSignals = [mergedSignals merge:someSignal];
By the way, -finally:
doesn't add side effects to an existing signal. Rather, it returns a new signal with side effects. The following does nothing because the returned signal is discarded and never subscribed to:
[signal finally:^{
// Remove the signal from the set to release it
self.signals = [[NSSet alloc] initWithArray:[[self.signals rac_sequence] ignore:signal].array];
}];
Thanks! I like the second form.
This helped me in 2019. Thanks a lot @brow