Reactivecocoa: Meilleur modèle pour les commandes annulables

Créé le 14 mai 2014  ·  4Commentaires  ·  Source: ReactiveCocoa/ReactiveCocoa

J'ai recherché un modèle approprié pour les commandes qui peuvent être annulées.

Voici le scénario:
L'utilisateur Joe souhaite se connecter au service Twitter sur son appareil. Il y a un bouton sur l'écran qui dit Twitter et lorsque l'utilisateur appuie dessus, le processus de connexion démarre et le texte sur le bouton change pour annuler. Le processus de connexion peut prendre une longue période de temps (30 secondes par exemple) et si l'utilisateur appuie à nouveau sur le bouton pendant ce temps, la connexion existante sera annulée.

J'ai essayé de nombreuses façons différentes de faire fonctionner ce produit, mais elles ont toutes une très mauvaise odeur. Voici la meilleure solution que j'ai trouvée jusqu'à présent:

<strong i="9">@property</strong> (strong, nonatomic) RACCommand *twitterLoginCommand;
<strong i="10">@property</strong> (strong, nonatomic) RACCommand *cancelCommand;
<strong i="11">@property</strong> (strong, nonatomic) id authenticatedUser;
<strong i="12">@property</strong> (weak, nonatomic) RACDisposable * authenticationDisposable;

-(void) viewDidLoad {
  RAC(self, twitterButton.rac_command, self.twitterLoginCommand) = [[RACObserve(self, twitterLoginCommand.executing) flatten]
  map:^id(NSNumber * value) {
    @strongify(self);
    if (value.boolValue) {
      return self.cancelCommand;
    } else {
      return self.twitterLoginCommand;
    }
  }];
}

-(RACCommand *) cancelCommand {
  if (!_cancelCommand) {
    @weakify(self);
    _cancelCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
      @strongify(self);
      [self.authenticationDisposable dispose];

      return [RACSignal empty];
    }];
  }

  return _cancelCommand;
}

- (RACCommand *)twitterLoginCommand {
  if (!_twitterLoginCommand) {
    @weakify(self);
    _twitterLoginCommand = [[RACCommand alloc]initWithSignalBlock: ^RACSignal *(UIButton *button) {
      @strongify(self);

      RACSignal * signal = [self twitterSignInSignal];
      self.authenticationDisposable = [signal subscribeNext:^(FAUser * user) {
        self.authenticatedUser = user;
      }error:^(NSError *error) {
        self.authenticationDisposable = nil;
      }];
      return signal;
    }];
  }

  return _twitterLoginCommand;
}

- (RACSignal *)twitterSignInSignal {
//Left out, returns a signal with a user
}

À l'origine, j'avais la commande Twitter souscrite dans viewDidLoad et utilisant un takeUntil pour le signal d'annulation (plutôt que d'utiliser le jetable et de s'abonner avec la commande), mais cela ne semblait pas empêcher la commande de s'exécuter immédiatement après l'annulation (la tâche de connexion resterait en cours d'exécution jusqu'à ce que le signal traite le takeUntil).

question

Commentaire le plus utile

Essaye celui-là.

_twitterLoginCommand = [[RACCommand alloc] initWithSignalBlock:^(id _) {
      @strongify(self);
      return [[self 
          twitterSignInSignal] 
          takeUntil:self.cancelCommand.executionSignals];
    }];

RAC(self.authenticatedUser) = [self.twitterLoginCommand.executionSignals switchToLatest];

Je vous suggère de déplacer les créations de commandes vers la méthode init

Tous les 4 commentaires

Essaye celui-là.

_twitterLoginCommand = [[RACCommand alloc] initWithSignalBlock:^(id _) {
      @strongify(self);
      return [[self 
          twitterSignInSignal] 
          takeUntil:self.cancelCommand.executionSignals];
    }];

RAC(self.authenticatedUser) = [self.twitterLoginCommand.executionSignals switchToLatest];

Je vous suggère de déplacer les créations de commandes vers la méthode init

Cela a fonctionné comme un charme et tout sent bon. Merci, il m'a fallu quelques jours pour arriver aussi loin que j'étais, j'ai dû manquer quelque chose quand j'ai essayé une approche comme celle-là la dernière fois.

De rien!

RAC (self.authenticatedUser) = [self.twitterLoginCommand.executionSignals switchToLatest];
si changez-le en
RAC (self.authenticatedUser) = [self.twitterLoginCommand.executionSignals aplatir];
mieux ? @notxcain

Cette page vous a été utile?
0 / 5 - 0 notes