Xaree Lee
Xaree Lee

Reputation: 3387

Collect signal values to an array using ReactiveCocoa

I use ReactiveCocoa to record the taps in an array:

@interface ViewController : UIViewController
@property (strong, nonatomic) NSArray *first10Taps;
@property (strong, nonatomic) UITapGestureRecognizer *tapGesture;
@end

@implementation ViewController
- (void) viewDidLoad
{
  [super viewDidLoad];

  RACSignal *tapSignal = [[self.tapGesture rac_gestureSignal] map:^id(UITapGestureRecognizer *sender) {
    return [NSValue valueWithCGPoint:[sender locationInView:sender.view]];
  }];

  // This signal will send the first 10 tapping positions and then send completed signal.
  RACSignal *first10TapSignal = [tapSignal take:10];

  // Need to turn this signal to a sequence with the first 10 taps.
  RAC(self, first10Taps) = [first10TapSignal ...];
}
@end

How to turn this signal to an array signal?

I need to update the array every time a new value is sent.

Upvotes: 0

Views: 788

Answers (2)

Xaree Lee
Xaree Lee

Reputation: 3387

Thanks for Michał Ciuba's answer. Using -collect will only send the collection value when the upstream signal is completed.

I found the way using -scanWithStart:reduce: to produce a signal which will send the collection every time a next value is sent.

RAC(self, first10Taps) = [firstTapSetSignal scanWithStart:[NSMutableArray array]  reduce:^id(NSMutableArray *collectedValues, id next) {
  [collectedValues addObject:(next ?: NSNull.null)];
  return collectedValues;
}];

Upvotes: 3

Michał Ciuba
Michał Ciuba

Reputation: 7944

There is a method on RACSignal called, well, collect. Its documentation says:

Collects all receiver's nexts into a NSArray. Nil values will be converted to NSNull. This corresponds to the ToArray method in Rx. Returns a signal which sends a single NSArray when the receiver completes successfully.

So you can simply use:

RAC(self, first10Taps) = [first10TapSignal collect];

Upvotes: 4

Related Questions