使用MVVM和ReactiveCocoa,如何在iOS中处理委托模式?

使用MVVM和ReactiveCocoa,如何在iOS中处理委托模式?,ios,mvvm,reactive-cocoa,Ios,Mvvm,Reactive Cocoa,一种常见的情况是有一个视图控制器A,它有一些信息将被发送到视图控制器B;B将编辑信息,当B完成编辑信息后,B将调用委托方法更新A,并从导航控制器中弹出自身 如何使用MVVM和ReactiveCocoa处理此问题?通常,大量使用ReactiveCocoa会使您脱离委托模式。但是,由于您已经编写的大部分代码以及在iOS标准库中遇到的所有代码都使用它,因此能够与它交互仍然很重要 您需要使用-[NSObject rac_signalForSelector:]类别,该类别将在每次调用方法时向方法返回一个接

一种常见的情况是有一个视图控制器A,它有一些信息将被发送到视图控制器B;B将编辑信息,当B完成编辑信息后,B将调用委托方法更新A,并从导航控制器中弹出自身


如何使用MVVM和ReactiveCocoa处理此问题?

通常,大量使用ReactiveCocoa会使您脱离委托模式。但是,由于您已经编写的大部分代码以及在iOS标准库中遇到的所有代码都使用它,因此能够与它交互仍然很重要

您需要使用-[NSObject rac_signalForSelector:]类别,该类别将在每次调用方法时向方法返回一个接收参数的RACTuple值的信号,并在释放发送信号的对象时完成

假设您要显示一个UIViewController,其中包含用户可以选择的复选框列表,底部有一个“继续”按钮。由于选择随时间变化,因此可以将其表示为NSIndexSet值的RACSignal。在本例中,假设您必须按原样使用该类,并且该类当前声明了一个委托模式,其中包含以下内容:

@class BSSelectionListViewController;
@protocol BSSelectionListViewControllerDelegate <NSObject>
   - (void)listChangedSelections:(BSSelectionListViewController*)list;
   - (void)listContinueTouched:(BSSelectionListViewController*)list;
@end
在将此UIViewController推送到堆栈上之前,您需要为它可以调用的委托方法创建信号:

RACSignal* continueTouched = [[[self rac_signalForSelector:@selector(listContinueTouched:)]
                                  takeUntil:list.rac_willDeallocSignal]
                                  filter:^BOOL(RACTuple* vcTuple)
    {
        return vcTuple.first == listVC;
    }];

    RACSignal* selections = [[[[self rac_signalForSelector:@selector(listChangedSelections:)]
                              takeUntil:list.rac_willDeallocSignal]
                              filter:^BOOL(RACTuple* vcTuple)
    {
        return vcTuple.first == listVC;
    }]
                             map:^id(RACTuple* vcTuple)
    {
        return [vcTuple.first selections];
    }];
然后你可以订阅这些信号来做任何你需要的副作用。可能是这样的:

RAC(self, firstChoiceSelected) = [selections map:^id(NSIndexSet* selections)
    {
        return @([selections containsIndex:0]);
    }];

因为您可能有几个您是其代表的屏幕,所以您需要确保在您的RAC信号中只过滤到这一个

ReactiveCocoa将实际实现这些方法—委托协议中的方法。但是,为了让编译器满意,您应该添加存根

- (void)listChangedSelections:(BSSelectionListViewController *)list {}
- (void)listContinueTouched:(BSSelectionListViewController*)list {}

在我看来,这是对标准委托模式的改进,在标准委托模式中,您需要声明一个实例变量来保存selection view控制器,并检入委托方法中哪个控制器正在调用您。ReactiveCocoa的rac_signalForSelector方法可以减少该视图控制器随时间变化到局部变量而不是实例变量的状态范围。它还允许您明确地处理对选择的更改

通常,大量使用ReactiveCocoa会使您脱离委托模式。但是,由于您已经编写的大部分代码以及在iOS标准库中遇到的所有代码都使用它,因此能够与它交互仍然很重要

您需要使用-[NSObject rac_signalForSelector:]类别,该类别将在每次调用方法时向方法返回一个接收参数的RACTuple值的信号,并在释放发送信号的对象时完成

假设您要显示一个UIViewController,其中包含用户可以选择的复选框列表,底部有一个“继续”按钮。由于选择随时间变化,因此可以将其表示为NSIndexSet值的RACSignal。在本例中,假设您必须按原样使用该类,并且该类当前声明了一个委托模式,其中包含以下内容:

@class BSSelectionListViewController;
@protocol BSSelectionListViewControllerDelegate <NSObject>
   - (void)listChangedSelections:(BSSelectionListViewController*)list;
   - (void)listContinueTouched:(BSSelectionListViewController*)list;
@end
在将此UIViewController推送到堆栈上之前,您需要为它可以调用的委托方法创建信号:

RACSignal* continueTouched = [[[self rac_signalForSelector:@selector(listContinueTouched:)]
                                  takeUntil:list.rac_willDeallocSignal]
                                  filter:^BOOL(RACTuple* vcTuple)
    {
        return vcTuple.first == listVC;
    }];

    RACSignal* selections = [[[[self rac_signalForSelector:@selector(listChangedSelections:)]
                              takeUntil:list.rac_willDeallocSignal]
                              filter:^BOOL(RACTuple* vcTuple)
    {
        return vcTuple.first == listVC;
    }]
                             map:^id(RACTuple* vcTuple)
    {
        return [vcTuple.first selections];
    }];
然后你可以订阅这些信号来做任何你需要的副作用。可能是这样的:

RAC(self, firstChoiceSelected) = [selections map:^id(NSIndexSet* selections)
    {
        return @([selections containsIndex:0]);
    }];

因为您可能有几个您是其代表的屏幕,所以您需要确保在您的RAC信号中只过滤到这一个

ReactiveCocoa将实际实现这些方法—委托协议中的方法。但是,为了让编译器满意,您应该添加存根

- (void)listChangedSelections:(BSSelectionListViewController *)list {}
- (void)listContinueTouched:(BSSelectionListViewController*)list {}
在我看来,这是对标准委托模式的改进,在标准委托模式中,您需要声明一个实例变量来保存selection view控制器,并检入委托方法中哪个控制器正在调用您。ReactiveCocoa的rac_signalForSelector方法可以减少该视图控制器随时间变化到局部变量而不是实例变量的状态范围。它还允许您明确地处理对选择的更改