常见的情况是拥有一个视图控制器A
,它有一些信息将发送到View Controller B
;并且B
将编辑信息,当B
完成信息编辑后,B
将调用委托方法更新A
,并从导航控制器弹出自己。
如何使用MVVM和ReactiveCocoa处理此问题?
答案 0 :(得分:4)
一般来说,大量使用ReactiveCocoa会开始让你离开委托模式。但是,由于您已编写的大部分代码以及您在iOS标准库中遇到的所有代码都使用它,因此能够与其进行交互仍然很重要。
您希望使用-[NSObject rac_signalForSelector:]
类别,该类别将返回每次调用方法时接收RACTuple
参数值的信号,并在对象完成时完成发送信号已被解除分配。
我们假设您要显示一个UIViewController
,其中包含用户可以选择的复选框列表,底部有一个继续按钮。由于选择会随着时间的推移而变化,因此您可以将其表示为RACSignal
NSIndexSet
个值。出于本示例的目的,我们假设您必须按原样使用此类,并且它当前声明了包含以下内容的委托模式:
@class BSSelectionListViewController;
@protocol BSSelectionListViewControllerDelegate <NSObject>
- (void)listChangedSelections:(BSSelectionListViewController*)list;
- (void)listContinueTouched:(BSSelectionListViewController*)list;
@end
当您从其他位置呈现视图控制器时(如导航堆栈顶部的UIViewController
),您将创建视图控制器并将self指定为委托。它可能看起来像
BSSelectionListViewController* listVC = [[BSSelectionListViewController alloc] initWithQuestion:question listChoices:choices selections:idxSet];
listVC.delegate = self;
[self.navigationController pushViewController:listVC];
在将此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]);
}];
和
@weakify(self)
[continueTouched subscribeNext:^(id x)
{
@strongify(self)
[self.navigationController popToViewController:self];
}];
因为您可能有多个这样的屏幕是您的代表,所以您希望确保在RACSignals中过滤到这一个。
ReactiveCocoa实际上会为您实现这些方法(委托协议中的方法)。但是,为了让编译器满意,您应该添加存根。
- (void)listChangedSelections:(BSSelectionListViewController *)list {}
- (void)listContinueTouched:(BSSelectionListViewController*)list {}
这是IMO,对标准委托模式的改进,您需要声明一个实例变量来保存选择视图控制器,并检查控制器呼叫您的委托方法。 ReactiveCocoa的rac_signalForSelector
方法可以将该状态(此视图控制器随时间变化)的范围缩小到局部变量而不是实例变量。它还允许您明确处理选择的更改。