How to handle table data queries using RACCommands

I have a ViewModel for a UITableView that contains an array of data items. UITableView implements pull-to-refresh and infinite scroll behavior. Data items are requested through RestKit from the server paginated, which means that I need to somehow track the current page. I created 2 separate RACCommands to distinguish between updates and endless scrolling, where the update always loads page 0. It all works, but I don't like it, and I want to know if there is a better way to do this. Plus now two commands can be executed simultaneously, which is not intended.

@interface TableDataViewModel ()

@property(nonatomic, readonly) RestApiConnector *rest;
@property(nonatomic) int page;
@property(nonatomic) NSMutableArray *data;
@property(nonatomic) RACCommand *loadCommand;
@property(nonatomic) RACCommand *reloadCommand;

@end

@implementation TableDataViewModel

objection_requires_sel(@selector(rest))

- (id)init {
    self = [super init];
    if (self) {
        [self configureLoadCommands];
        [self configureActiveSignal];
    }
    return self;
}

- (void)configureActiveSignal {
    [self.didBecomeActiveSignal subscribeNext:^(id x) {
        if (!self.data) {
            [self.reloadCommand execute:self];
        }
    }];
}

- (void)configureLoadCommands {
    self.loadCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
        return [self.rest dataSignalWithPage:self.page];
    }];
    self.reloadCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
        return [self.rest dataSignalWithPage:self.page];
    }];
    self.loadCommand.allowsConcurrentExecution = FALSE;
    self.reloadCommand.allowsConcurrentExecution = FALSE;

    [self.reloadCommand.executionSignals subscribeNext:^(id x) {
        RAC(self, data) = [x map:^id(id value) {
            self.page = 0;
            return [value mutableCopy];
        }];
    }];

    [self.loadCommand.executionSignals subscribeNext:^(id x) {
        RAC(self, data) = [x map:^id(id value) {
            self.page++;
            if (self.data) {
                NSMutableArray *array = [self.data mutableCopy];
                [array addObjectsFromArray:value];
                return array;
            } else {
                return [value mutableCopy];
            }
        }];
    }];
}
@end

I just started using ReactiveCocoa, so I would appreciate any other advice for this.

Thank!

+4
1

ReactiveCocoa, .

, , - ( , ):

1  const NSUInteger kLoad   = 0;
2  const NSUInteger kReload = 1;
3
4  - (void)configureActiveSignal {
5      @weakify(self);
6      RACSignal *dba = [[self.didBecomeActiveSignal filter:^(id _) {
7              @strongify(self);
8              return self.data;
9          }]
10          mapReplace:@( kReload )];
11
12      RACSignal *ls = [self.command rac_liftSelector:@selector(execute:) withSignals:dba];
13      [[ls publish] connect];
14  }
15  
16  - (void)configureCommand {
17      @weakify(self);
18      self.command = [[RACCommand alloc] initWithSignalBlock:^(NSNumber *loadOrReload) {
19              @strongify(self);
20              return RACTuplePack(loadOrReload, [self.rest dataSignalWithPage:self.page]);
21          }];
22
23      RAC(self, page) = [self.command.executionSignals reduceEach:^(NSNumber *loadOrReload, id _) {
24              @strongify(self);
25              return kReload == loadOrReload.integerValue ? @0 : @( ++self.page );
26          }];
27      RAC(self, data) = self.command.executionSignals reduceEach:^(NSNumber *loadOrReload, NSArray *data) {
28              @strongify(self);
29              if (kReload == loadOrReload.integerValue)
30              {
31                  return [data mutableCopy];
32              }
33              else
34              {
35                  NSMutableArray *ma = [self.data mutableCopy];
36                  [ma addObjectsFromArray:data]
37                  return ma;
38              }
39          }];
40
41      self.command.allowsConcurrentExecution = NO;

Nota bene, . , .

  • , , command. , , , , , 18.
  • 5: . self , self ( , ). ReactiveCocoa @strongify/weakify, . , , self , ( self, , ), , . @strongify , ARC.
  • 6: didBecomeActive self.command kReload ( reloadCommand), self.data != nil, -filter:.
  • 12: , [self.command execute:], , . , , self.loadCommand, , @( kLoad ).
  • 13: -publish/connect , , . RAC 2.x.
  • 18:. , NSNumber , , , 6. , , , , , -execute: . , , , .
  • 23: RAC() ( ) -configureCommand. , self.page 0, ++self.page, , kLoad kReload. -reduceEach: - , , . self.page -reduceEach:.. , . , -, RAC(self, page), , , . , - self.page , .
  • 27: , 23, self.page self.data. -reduceEach: (), kLoad, kReload, ivar.
+3

Source: https://habr.com/ru/post/1532696/


All Articles