我正在构建一个可滑动的单元格,为该单元格添加一个平移手势。基本上,它具有与邮箱应用程序中的单元格相同的外观和感觉,其中您有一个顶视图,您可以向左或向右滑动以显示下面的另一个视图(revealView)。
我想用反应式方法构建它,所以我这样做的方式是:
首先,当我设置视图和平移手势时,我正在过滤rac_gestureSignal以获取手势的当前状态并使用绑定更新顶视图位置(这里简化了一些实现细节)以及在手势结束/取消时隐藏/显示revealView。当panDirection或revealView更改(为了相应地更新revealView框架)时,我也调用setNeedsLayout来合并来自其值的信号,以及删除重复使用单元格的显示视图:
- (void)setupView
{
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:nil];
panGesture.delegate = self;
RACSignal *gestureSignal = [panGesture rac_gestureSignal],
*beganOrChangeSignal = [gestureSignal filter:^BOOL(UIGestureRecognizer *gesture) {
return gesture.state == UIGestureRecognizerStateChanged || gesture.state == UIGestureRecognizerStateBegan;
}],
*endOrCancelSignal = [gestureSignal filter:^BOOL(UIGestureRecognizer *gesture) {
return gesture.state == UIGestureRecognizerStateEnded || gesture.state == UIGestureRecognizerStateCancelled;
}];
RAC(self, contentSnapshotView.center) = [beganOrChangedSignal map:^id(id value) {
return [NSValue valueWithCGPoint:[self centerPointForTranslation:[panGesture translationInView:self]]];
}];
[beganOrChangeSignal subscribeNext:^(UIPanGestureRecognizer *panGesture) {
[self updateTopViewFrame];
[panGesture setTranslation:CGPointZero inView:self];
}];
[[endOrCancelSignal filter:^BOOL(UIPanGestureRecognizer *gestureRecognizer) {
return [self shouldShowRevealView];
}] subscribeNext:^(id x) {
[self showRevealViewAnimated:YES];
}];
[[endOrCancelSignal filter:^BOOL(UIPanGestureRecognizer *gestureRecognizer) {
return [self shouldHideRevealView];
}] subscribeNext:^(id x) {
[self hideRevealViewAnimated:YES];
}];
[[RACSignal merge:@[RACObserve(self, panDirection), RACObserve(self, revealView)]] subscribeNext:^(id x) {
[self setNeedsLayout];
}];
[[self rac_prepareForReuseSignal] subscribeNext:^(id x) {
[self.revealView removeFromSuperview];
self.revealView = nil;
}];
[self addGestureRecognizer:panGesture];
}
然后,我正在暴露一个信号属性(revealViewSignal),当显示视图显示/隐藏时,它将发送YES / NO值。因此,您可以订阅此信号,从而在视图更改其状态时执行操作。在内部,此信号将是每个显示/隐藏动画结束后发送下一个事件的RACS主题:
- (void)showRevealViewAnimated:(BOOL)animated
{
[UIView animateWithDuration:animated ? 0.1 : 0.0
animations:^{
// SHOW ANIMATIONS
}
completion:^(BOOL finished) {
[(RACSubject *)self.revealViewSignal sendNext:@(YES)];
}];
}
- (void)hideRevealViewAnimated:(BOOL)animated
{
[UIView animateWithDuration:animated ? 0.1 : 0.0
animations:^{
// HIDE ANIMATIONS
}
completion:^(BOOL finished) {
[(RACSubject *)self.revealViewSignal sendNext:@(NO)];
}];
}
一切都按预期工作但我只是想知道这是否是以RAC方式构建此类视图的正确方法。此外,有两种手势识别器委托方法,我很乐意在上面的相同设置方法中设置,但我无法弄清楚是否可以在这里使用rac_signalForSelector:fromProtocol:方法,所以我最终实现了它们一如既往:
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
return [self checkIfGestureShouldBegin:gestureRecognizer];
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return [self checkIfGestureShouldRecognize:gestureRecognizer];
}
任何帮助都会得到很高的评价,谢谢!
答案 0 :(得分:1)
不幸的是,目前无法使用RAC来实现返回值的协议方法。
这是一个棘手的问题,因为不需要信号同步发送值,但显然你需要在调用委托方法时返回<em>某些。您可能不想要阻止信号,因为它很容易死或锁定。