简体   繁体   中英

How to send the RACSignal to cell's viewMode when click a button outside of the Cells

I have a button on navigation bar, that named "Edit". And a UICollectionView show with some content. To click the "Edit" button will make into a "EditMode", and the button's title become "Done", the UICollectionView 's cell should also updated. Click the "Done" button will do the reverse.

I have write the code bellow: Now after click the "Edit"|"Done" button, the hole collection View will be updated with a refresh, since there's images in the cell get from service which I don't update them. I prefer just update the icon by Cell's signal. but How to refactor the code?

1.viewController's -(void)viewDidLoad

 [[[[self.editButton rac_signalForControlEvents:UIControlEventTouchUpInside]
    doNext:^(UIButton *sender) {
        if ([sender.titleLabel.text isEqualToString:@"Edit"]) {
            [sender setTitle:@"Done" forState:UIControlStateNormal];
        }else{
            [sender setTitle:@"Edit" forState:UIControlStateNormal];
        }
    }]
    flattenMap:^RACStream *(UIButton *sender) {
        BOOL isEditMode = [sender.titleLabel.text isEqualToString:@"Edit"];
        return [RACSignal return:@(isEditMode)];
    }] subscribeNext:^(NSNumber* x) {
        [self.viewModel setEditMode:x.boolValue];
    }];

  // Binding to view model
  [[RACObserve(self.viewModel, dataArray) 
     deliverOnMainThread] subscribeNext:^(id x) {
         @strongify(self);
         [self.collectionView reloadData];
     }];

2.1.viewController's ViewModel's property

 @property (nonatomic, assign, getter= isEditMode) BOOL editMode;

2.2.viewController's ViewModel's -(id)init

  self.isEditModeSignal = RACObserve(self, isEditMode);

3.viewController's - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath

  DataModel* item = [self.dataArray objectAtIndex:indexPath.row];
  [cellViewModel setDataModel:item
         withIsEditModeSignal:self.viewModel.isEditModeSignal];
  [Cell setCellViewModel:cellViewModel];

4.Cell's ViewModel's -(void)setDataModel:(DataModel)data withIsEditModeSignal:(RACSignal*)isEditModeSignal

 self.thing1Signal = [[RACSignal combineLatest:@[self.isEditModeSignal,
                                                     other1Signal,
                                                     other2Signal]
                                 reduce:^id(NSNumber *isEditMode,
                                            NSNumber *other1,
                                            NSNumber *other2){
                                     return @(isEditMode.boolValue && other1.boolValue && other2.boolValue);
                                 }];

 self.thing2Signal = [[RACSignal combineLatest:@[self.isEditModeSignal,
                                                     other3Signal,
                                                     other4Signal]
                                 reduce:^id(NSNumber *isEditMode,
                                            NSNumber *other3,
                                            NSNumber *other4){
                                     return @(isEditMode.boolValue && other3.boolValue && other4.boolValue);
                                 }];

5.Cell.m's -(void)setCellViewModel:(CellViewModel*)viewModel

 [[[self.viewModel.thing1Signal deliverOnMainThread] takeUntil:self.rac_prepareForReuseSignal]  subscribeNext:^(NSNumber *isHidden) {
  self.icon1.hidden = isHidden.boolValue;
 }];

 [[[self.viewModel.thing2Signal deliverOnMainThread] takeUntil:self.rac_prepareForReuseSignal]  subscribeNext:^(NSNumber *isHidden) {
  self.icon2.hidden = isHidden.boolValue;
 }];

Aha, I found the problem: I use self.isEditModeSignal = RACObserve(self, isEditMode); Which I should use self.isEditModeSignal = RACObserve(self, editMode); . That's the root cause.

This code is really bad. You're not using ReactiveCocoa the way it is meant to. A better way is to be binding between cellviewmodels and collectionview viewmodels. No need to trigger a refresh at all.

Like so:

// In cell viewmodel's init method:
RAC(self,isEditMode) = RACObserve(self, collectionViewModel.isEditMode); 
//Bind view stuff to: RACObserve(self,isEditMode)

//In collectionview viewmodel init method:
RAC(self,isEditMode) = [[[self.editButton.rac_command executionSignals] flatten] scanWithStart:@NO reduce:id^(NSNumber * running, id next) {
  return @(![running boolValue]);
}];

//In collectionview
RAC(self.editButton.titleLabel, text) = [RACObserve(self.viewModel, isEditMode) map:(NSString *)^(NSNumber * x) {
  [x boolValue] ? @"Edit" : @"Done";
}];

And instead of using combineLatest use the if signal.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM