J'ai un PoC d'une classe utilisant un signal répété avec un intervalle variable:
// Repeat.h
#import <Foundation/Foundation.h>
<strong i="6">@interface</strong> Repeat : NSObject
- (instancetype)initWithInterval:(NSInteger)interval;
<strong i="7">@property</strong> (assign, nonatomic) NSInteger interval;
<strong i="8">@property</strong> (readonly, nonatomic) RACSubject *dataSubject;
<strong i="9">@end</strong>
// Repeat.m
#import <ReactiveCocoa/ReactiveCocoa.h>
#import "Repeat.h"
<strong i="12">@interface</strong> Repeat ()
<strong i="13">@property</strong> (readwrite, strong, nonatomic) RACSubject *dataSubject;
<strong i="14">@property</strong> (readwrite, strong, nonatomic) RACSignal *dataSignal;
<strong i="15">@end</strong>
<strong i="16">@implementation</strong> Repeat
- (instancetype)initWithInterval:(NSInteger)interval
{
self = [super init];
if (self) {
self.dataSubject = [RACSubject subject];
self.dataSignal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
static int i = 0;
[subscriber sendNext:@(i++)];
return nil;
}];
self.interval = interval;
[RACObserve(self, interval) subscribeNext:^(id x) {
RACSignal *limit = [RACObserve(self, interval) skip:1];
RACSignal *repeater = [[RACSignal interval:[x integerValue]
onScheduler:[RACScheduler mainThreadScheduler]]
takeUntil:limit];
RACSignal *tickSignal = [repeater doCompleted:^{
NSLog(@"interval changed to: %lu", self.interval);
}];
[[tickSignal flattenMap:^RACStream *(id value) { // *
return self.dataSignal;
}] subscribeNext:^(id x) {
[self.dataSubject sendNext:x];
}];
}];
}
return self;
}
<strong i="17">@end</strong>
L'utilisation serait la suivante:
Repeat *repeater = [[Repeat alloc] initWithInterval:3];
[repeater.dataSubject subscribeNext:^(id x) {
// do something with x
}];
...
// somehwere else in the code
repeater.interval = 5;
Cela me permet de conserver l'abonnement et de ne modifier que l'intervalle de livraison des valeurs de signal. Je m'inquiète de la partie que le consommateur doit réellement souscrire au sujet plutôt qu'au signal. Je comprends que ce n'est pas un scénario courant et que les directives encouragent en fait à éviter les sujets si possible. J'ai essayé d'exposer dataSignal
dans l'interface publique et de remplacer la partie marquée par // *
comme suit:
[tickSignal subscribeNext:^(id x) {
[self.dataSignal replayLast];
}];
Mais cela ne fonctionnerait pas du tout et seule la valeur initiale serait envoyée. Quelqu'un d'autre a-t-il essayé de mettre en œuvre ce que j'essaie de réaliser ici? Je suis convaincu que RAC est capable de le faire et mon PoC n'est qu'un vilain petit canard qui peut être grandement amélioré.
L'essentiel peut être trouvé ici: https://gist.github.com/eimantas/51d9dfc81136f340a829
Mise à jour: basée sur la réponse de @jspahrsummers à la question sur stackoverflow: http://stackoverflow.com/questions/15075075/when-to-use-racreplaysubject-vs-racmulticastconnection
Il semble que RACMulticastConnection fasse la même chose - exposer RACSubject
comme RACSignal
, donc je suppose que je devrais faire la même chose alors?
Si le minuteur n'est jamais vraiment censé se terminer, vous pouvez créer une méthode récursive qui exécute concat:[RACSignal delay:N]
et s'invoque à partir de concat:[RACSignal defer:^{}]
après cela.
En d'autres termes, insérez des délais de N secondes entre une série infinie de votre propre signal.
La minuterie peut être interrompue sur commande de l'utilisateur. Et en ce qui concerne la récursivité - mon CS peut être rouillé, mais cela ne créerait-il pas finalement le débordement du cadre de la pile?
@eimantas Non, car le délai ne sera pas synchrone. RAC quittera le cadre et reviendra au code plus tard une fois le délai écoulé.
Je suis désolé, mais je ne comprends toujours pas votre idée (en particulier - sur quoi dois-je appeler concat:[RACSignal delay:N]
?
- (RACSignal *)doStuffRepeatedly {
return [[[RACSignal
defer:^{
// Do some stuff here
return [RACSignal empty];
}]
// Wait 5 seconds
concat:[RACSignal delay:5]]
then:^{
// Do more stuff
return [self doStuffRepeatedly];
}];
}
Fermeture en raison de l'inactivité.
Commentaire le plus utile